stage4/generate_c/generate_c.cc
changeset 594 c8092e909886
parent 592 99a284cec1f2
child 596 4efb11e44065
equal deleted inserted replaced
593:412780374bd3 594:c8092e909886
   347 /***********************************************************************/
   347 /***********************************************************************/
   348 
   348 
   349 #define MILLISECOND 1000000
   349 #define MILLISECOND 1000000
   350 #define SECOND 1000 * MILLISECOND
   350 #define SECOND 1000 * MILLISECOND
   351 
   351 
   352 /* A helper class that knows how to generate code for both the IL and ST languages... */
   352 unsigned long long calculate_time(symbol_c *symbol) {
   353 class calculate_time_c: public iterator_visitor_c {
   353   if (NULL == symbol) return 0;
   354   private:
       
   355     unsigned long long time;
       
   356     float current_value;
       
   357   
   354   
   358   public:
   355   interval_c *interval = dynamic_cast<interval_c *>(symbol);
   359     calculate_time_c(void){time = 0;};
   356   duration_c *duration = dynamic_cast<duration_c *>(symbol);
   360     
       
   361     unsigned long long get_time(void) {return time;};
       
   362 
       
   363     /* NOTE: we should really remove this function, and replace it with  extract_integer_value() (in absyntax_utils.h)
       
   364      *       but right now I don't want to spend time checking if this change will introduce some conversion bug
       
   365      *       since it returns a long long, and not a float!
       
   366      */
       
   367     void *get_integer_value(token_c *token) {
       
   368       std::string str = "";
       
   369       for (unsigned int i = 0; i < strlen(token->value); i++)
       
   370         if (token->value[i] != '_')
       
   371           str += token->value[i];
       
   372       current_value = atof(str.c_str());
       
   373       return NULL;
       
   374     }
       
   375 
       
   376     /* NOTE: this function is incomplete, as it should also be removing '_' inserted into the literal,
       
   377      *       but we leave it for now.
       
   378      *       In truth, we should really have an extract_real_value() in absyntax_util.h !!!
       
   379      */
       
   380     void *get_float_value(token_c *token) {
       
   381       current_value = atof(token->value);
       
   382       return NULL;
       
   383     }
       
   384 
       
   385 /******************************/
       
   386 /* B 1.2.1 - Numeric Literals */
       
   387 /******************************/
       
   388 
       
   389     void *visit(integer_c *symbol) {return get_integer_value(symbol);}
       
   390     
       
   391 /************************/
       
   392 /* B 1.2.3.1 - Duration */
       
   393 /************************/
       
   394   
   357   
       
   358   if ((NULL == interval) && (NULL == duration)) ERROR;
       
   359 
       
   360   if (NULL != duration) {
   395     /* SYM_REF2(duration_c, neg, interval) */
   361     /* SYM_REF2(duration_c, neg, interval) */
   396     void *visit(duration_c *symbol) {
   362     if (duration->neg != NULL)
   397       if (symbol->neg != NULL)
   363       {STAGE4_ERROR(duration, duration, "Negative TIME literals are not currently supported"); ERROR;}
   398         {STAGE4_ERROR(symbol, symbol, "Negative TIME literals are not currently supported"); ERROR;}
   364     return calculate_time(duration->interval);
   399       symbol->interval->accept(*this);
   365   }
   400       return NULL;
   366 
   401     }
   367   if (NULL != interval) {
   402     
       
   403     /* SYM_TOKEN(fixed_point_c) */
       
   404     void *visit(fixed_point_c *symbol) {return get_float_value(symbol);}
       
   405     
       
   406     
       
   407     /* SYM_REF5(interval_c, days, hours, minutes, seconds, milliseconds) */
   368     /* SYM_REF5(interval_c, days, hours, minutes, seconds, milliseconds) */
   408     void *visit(interval_c *symbol) {
   369       unsigned long long int time_ull = 0; 
   409       current_value = 0;
   370       long double            time_ld  = 0;
   410       if (NULL != symbol->milliseconds) symbol->milliseconds->accept(*this);
   371       /*
   411       time += (unsigned long long)(current_value * MILLISECOND);
   372       const unsigned long long int MILLISECOND = 1000000;
       
   373       const unsigned long long int      SECOND = 1000 * MILLISECOND
       
   374       */
       
   375       
       
   376       if (NULL != interval->milliseconds) {
       
   377         if      (VALID_CVALUE( int64, interval->milliseconds) &&           GET_CVALUE( int64, interval->milliseconds) < 0) ERROR; // interval elements should always be positive!
       
   378         if      (VALID_CVALUE( int64, interval->milliseconds)) time_ull += GET_CVALUE( int64, interval->milliseconds) * MILLISECOND;
       
   379         else if (VALID_CVALUE(uint64, interval->milliseconds)) time_ull += GET_CVALUE(uint64, interval->milliseconds) * MILLISECOND;
       
   380         else if (VALID_CVALUE(real64, interval->milliseconds)) time_ld  += GET_CVALUE(real64, interval->milliseconds) * MILLISECOND;
       
   381         else ERROR; // if (NULL != interval->milliseconds) is true, then it must have a valid constant value!
       
   382       }
   412    
   383    
   413       current_value = 0;
   384       if (NULL != interval->seconds     ) {
   414       if (NULL != symbol->seconds)      symbol->seconds->accept(*this);
   385         if      (VALID_CVALUE( int64, interval->seconds     ) &&           GET_CVALUE( int64, interval->seconds     ) < 0) ERROR; // interval elements should always be positive!
   415       time += (unsigned long long)(current_value * SECOND);
   386         if      (VALID_CVALUE( int64, interval->seconds     )) time_ull += GET_CVALUE( int64, interval->seconds     ) * SECOND;
   416    
   387         else if (VALID_CVALUE(uint64, interval->seconds     )) time_ull += GET_CVALUE(uint64, interval->seconds     ) * SECOND;
   417       current_value = 0;
   388         else if (VALID_CVALUE(real64, interval->seconds     )) time_ld  += GET_CVALUE(real64, interval->seconds     ) * SECOND;
   418       if (NULL != symbol->minutes)      symbol->minutes->accept(*this);
   389         else ERROR; // if (NULL != interval->seconds) is true, then it must have a valid constant value!
   419       time += (unsigned long long)(current_value * 60 * SECOND);
   390       }
   420    
   391 
   421       current_value = 0;
   392       if (NULL != interval->minutes     ) {
   422       if (NULL != symbol->hours)        symbol->hours->accept(*this);
   393         if      (VALID_CVALUE( int64, interval->minutes     ) &&           GET_CVALUE( int64, interval->minutes     ) < 0) ERROR; // interval elements should always be positive!
   423       time += (unsigned long long)(current_value * 60 * 60 * SECOND);
   394         if      (VALID_CVALUE( int64, interval->minutes     )) time_ull += GET_CVALUE( int64, interval->minutes     ) * SECOND * 60;
   424    
   395         else if (VALID_CVALUE(uint64, interval->minutes     )) time_ull += GET_CVALUE(uint64, interval->minutes     ) * SECOND * 60;
   425       current_value = 0;
   396         else if (VALID_CVALUE(real64, interval->minutes     )) time_ld  += GET_CVALUE(real64, interval->minutes     ) * SECOND * 60;
   426       if (NULL != symbol->days)         symbol->days->accept(*this);
   397         else ERROR; // if (NULL != interval->minutes) is true, then it must have a valid constant value!
   427       time += (unsigned long long)(current_value * 60 * 60 * 24 * SECOND);
   398       }
   428    
   399 
   429       return NULL;
   400       if (NULL != interval->hours       ) {
   430     }      
   401         if      (VALID_CVALUE( int64, interval->hours       ) &&           GET_CVALUE( int64, interval->hours       ) < 0) ERROR; // interval elements should always be positive!
       
   402         if      (VALID_CVALUE( int64, interval->hours       )) time_ull += GET_CVALUE( int64, interval->hours       ) * SECOND * 60 * 60;
       
   403         else if (VALID_CVALUE(uint64, interval->hours       )) time_ull += GET_CVALUE(uint64, interval->hours       ) * SECOND * 60 * 60;
       
   404         else if (VALID_CVALUE(real64, interval->hours       )) time_ld  += GET_CVALUE(real64, interval->hours       ) * SECOND * 60 * 60;
       
   405         else ERROR; // if (NULL != interval->hours) is true, then it must have a valid constant value!
       
   406       }
       
   407 
       
   408       if (NULL != interval->days        ) {
       
   409         if      (VALID_CVALUE( int64, interval->days        ) &&           GET_CVALUE( int64, interval->days        ) < 0) ERROR; // interval elements should always be positive!
       
   410         if      (VALID_CVALUE( int64, interval->days        )) time_ull += GET_CVALUE( int64, interval->days        ) * SECOND * 60 * 60 * 24;
       
   411         else if (VALID_CVALUE(uint64, interval->days        )) time_ull += GET_CVALUE(uint64, interval->days        ) * SECOND * 60 * 60 * 24;
       
   412         else if (VALID_CVALUE(real64, interval->days        )) time_ld  += GET_CVALUE(real64, interval->days        ) * SECOND * 60 * 60 * 24;
       
   413         else ERROR; // if (NULL != interval->days) is true, then it must have a valid constant value!
       
   414       }
       
   415 
       
   416       time_ull += time_ld;
       
   417       return time_ull;
       
   418   };
       
   419   ERROR; // should never reach this point!
       
   420   return 0; // humour the compiler!
   431 };
   421 };
   432 
   422 
   433 /***********************************************************************/
   423 /***********************************************************************/
   434 /***********************************************************************/
   424 /***********************************************************************/
   435 /***********************************************************************/
   425 /***********************************************************************/
   479     }
   469     }
   480 
   470 
   481 /*  TASK task_name task_initialization */
   471 /*  TASK task_name task_initialization */
   482 //SYM_REF2(task_configuration_c, task_name, task_initialization)  
   472 //SYM_REF2(task_configuration_c, task_name, task_initialization)  
   483     void *visit(task_initialization_c *symbol) {
   473     void *visit(task_initialization_c *symbol) {
   484       calculate_time_c calculate_time;
   474       unsigned long long time = calculate_time(symbol->interval_data_source);
   485       unsigned long long time = 0;
   475       if (time < 0)  ERROR;
   486       if (symbol->interval_data_source != NULL) {
   476       else           update_ticktime(time);
   487         symbol->interval_data_source->accept(calculate_time);
       
   488         time = calculate_time.get_time();
       
   489       }
       
   490       if (time > 0)
       
   491         update_ticktime(time);
       
   492       return NULL;
   477       return NULL;
   493     }
   478     }
   494 };    
   479 };    
   495 
   480 
   496 /***********************************************************************/
   481 /***********************************************************************/
   798             current_array_name += ss.str();
   783             current_array_name += ss.str();
   799           }
   784           }
   800           break;
   785           break;
   801         case arraydeclaration_im:
   786         case arraydeclaration_im:
   802           s4o_incl.print("[");
   787           s4o_incl.print("[");
   803           s4o_incl.print_integer(symbol->dimension);
   788           s4o_incl.print(symbol->dimension);
   804           s4o_incl.print("]");
   789           s4o_incl.print("]");
   805         default:
   790         default:
   806           generate_c_typedecl_c::visit(symbol);
   791           generate_c_typedecl_c::visit(symbol);
   807           break;
   792           break;
   808       }
   793       }
  1813       run_dt
  1798       run_dt
  1814     } declaretype_t;
  1799     } declaretype_t;
  1815 
  1800 
  1816     declaretype_t wanted_declaretype;
  1801     declaretype_t wanted_declaretype;
  1817 
  1802 
  1818     unsigned long common_ticktime;
  1803     unsigned long long common_ticktime;
  1819     
  1804     
  1820     const char *current_program_name;
  1805     const char *current_program_name;
  1821 
  1806 
  1822     typedef enum {
  1807     typedef enum {
  1823       assign_at,
  1808       assign_at,
  2190           else {
  2175           else {
  2191             s4o.print(s4o.indent_spaces);
  2176             s4o.print(s4o.indent_spaces);
  2192             current_task_name->accept(*this);
  2177             current_task_name->accept(*this);
  2193             s4o.print(" = ");
  2178             s4o.print(" = ");
  2194             if (symbol->interval_data_source != NULL) {
  2179             if (symbol->interval_data_source != NULL) {
  2195               calculate_time_c calculate_time;
  2180               unsigned long long int time = calculate_time(symbol->interval_data_source);
  2196               symbol->interval_data_source->accept(calculate_time);
       
  2197               unsigned long time = calculate_time.get_time();
       
  2198               if (time != 0) {
  2181               if (time != 0) {
  2199                 s4o.print("!(tick % ");
  2182                 s4o.print("!(tick % ");
  2200                 s4o.print_integer((int)(time / common_ticktime));
  2183                 s4o.print(time / common_ticktime);
  2201                 s4o.print(")");
  2184                 s4o.print(")");
  2202               }
  2185               }
  2203               else
  2186               else
  2204                 s4o.print("1");
  2187                 s4o.print("1");
  2205             }
  2188             }