stage4/generate_c/generate_c_st.cc
changeset 936 0f7bcc160568
parent 933 76324f461aed
child 941 c2ef93412407
equal deleted inserted replaced
935:be4373d07201 936:0f7bcc160568
   346        */
   346        */
   347       if (   get_datatype_info_c::is_function_block(symbol->record_variable->datatype)
   347       if (   get_datatype_info_c::is_function_block(symbol->record_variable->datatype)
   348           || get_datatype_info_c::is_sfc_step      (symbol->record_variable->datatype)) {
   348           || get_datatype_info_c::is_sfc_step      (symbol->record_variable->datatype)) {
   349         if (NULL == symbol->record_variable->scope) ERROR;
   349         if (NULL == symbol->record_variable->scope) ERROR;
   350         search_var_instance_decl_c search_var_instance_decl(symbol->record_variable->scope);
   350         search_var_instance_decl_c search_var_instance_decl(symbol->record_variable->scope);
   351         if (search_var_instance_decl_c::external_vt == search_var_instance_decl.get_vartype(get_var_name_c::get_last_field(symbol->record_variable)))
   351         if      (search_var_instance_decl_c::external_vt == search_var_instance_decl.get_vartype(get_var_name_c::get_last_field(symbol->record_variable)))
   352           s4o.print("->");
   352           s4o.print("->"); /* please read the comment in visit(deref_operator_c *) tio understand what this line is doing! */
       
   353         else if (dynamic_cast<deref_operator_c *>(symbol->record_variable) != NULL)
       
   354           s4o.print("->"); /* please read the comment in visit(deref_operator_c *) tio understand what this line is doing! */
   353         else  
   355         else  
   354           s4o.print(".");
   356           s4o.print(".");
   355         symbol->field_selector->accept(*this);
   357         symbol->field_selector->accept(*this);
   356       }
   358       }
   357       break;
   359       break;
   358     case complextype_suffix_vg:
   360     case complextype_suffix_vg:
   359       symbol->record_variable->accept(*this);
   361       symbol->record_variable->accept(*this);
   360       // the following condition MUST be a negation of the above condition used in the 'case complextype_base_vg:'
   362       // the following condition MUST be a negation of the above condition used in the 'case complextype_base_vg:'
   361       if (!(   get_datatype_info_c::is_function_block(symbol->record_variable->datatype)     // if the record variable is not a FB... 
   363       if (!(   get_datatype_info_c::is_function_block(symbol->record_variable->datatype)     // if the record variable is not a FB... 
   362             || get_datatype_info_c::is_sfc_step      (symbol->record_variable->datatype))) { // ...nor an SFC step name, then it will certainly be a structure!
   364             || get_datatype_info_c::is_sfc_step      (symbol->record_variable->datatype))) { // ...nor an SFC step name, then it will certainly be a structure!
   363         s4o.print(".");
   365         if (dynamic_cast<deref_operator_c *>(symbol->record_variable) != NULL)
       
   366           s4o.print("->"); /* please read the comment in visit(deref_operator_c *) tio understand what this line is doing! */
       
   367         else
       
   368           s4o.print(".");
   364         symbol->field_selector->accept(*this);
   369         symbol->field_selector->accept(*this);
   365       }
   370       }
   366       break;
   371       break;
   367     default:
   372     default:
   368       if (this->is_variable_prefix_null()) {
   373       if (this->is_variable_prefix_null()) {
       
   374         /* We are writing code for a FUNCTION. In this case, deref_operator_c are not transformed into the C pointer derefence syntax '->' (e.g. ptr->elem).
       
   375          * We use instead the '*' syntax (e.g. (*ptr).elem)
       
   376          * While in FB the '->' is generated by this structured_variable_c visitor, in Functions the '*' syntax is generated by the deref_operator_c visitor
       
   377          * This is why here we do NOT have --> {if (dynamic_cast<deref_operator_c *>(symbol->record_variable) != NULL)  ..}
       
   378 	 *  
       
   379 	 * please read the comment in visit(deref_operator_c *) for more information!
       
   380          */
   369         symbol->record_variable->accept(*this);
   381         symbol->record_variable->accept(*this);
   370         s4o.print(".");
   382         s4o.print(".");
   371         symbol->field_selector->accept(*this);
   383         symbol->field_selector->accept(*this);
   372       }
   384       }
   373       else
   385       else
   461 /* B.3 - Language ST (Structured Text) */
   473 /* B.3 - Language ST (Structured Text) */
   462 /***************************************/
   474 /***************************************/
   463 /***********************/
   475 /***********************/
   464 /* B 3.1 - Expressions */
   476 /* B 3.1 - Expressions */
   465 /***********************/
   477 /***********************/
       
   478 void *visit(deref_operator_c *symbol) {
       
   479   /* When producing C code for FUNCTION_BLOCKS, we use the '*' syntax (e.g. (*ptr).elem)
       
   480    * When producing C code for a FUNCTION_BLOCK, the deref_operator_c are transformed in two ways, depending on where they occur.
       
   481    *    - deref_operator between a struct and its elem (e.g. struct_ref^.elem1) 
       
   482    *        are transformed into C using the C pointer derefence syntax '->' (e.g. struct_ref->elem1).
       
   483    *        (In this case, '->' is generated by this structured_variable_c visitor)
       
   484    *    - deref_operator at the end of a struct variable (e.g. struct.elem_ptr^)
       
   485    *        are transformed using the '*' syntax for C pointer dereferencing (e.g. *(struct.elem_ptr) )
       
   486    * 
       
   487    *   NOTE: Ideally, we should always use the '*' C pointer dereferencing syntax. However, due to the
       
   488    *         was the GET_VAR and SET_VAR are transformed into C, this does not work for '^' between a struct and its 
       
   489    *         element (e.g. struct_ref^.elem), which is whey in this case only we use the '->' syntax.
       
   490    *   NOTE: The use of the -> syntax means that pointers to pointers are not supported betweem a struct and its elem
       
   491    *         (e.g. . struct_ref_ref^^.elem) as this would be transformed into the invalid C code struct_ref_ref->->elem.
       
   492    *         This is why we add a test for this case, and bug out with an error if we encounter it!!
       
   493    */
       
   494   if (this->is_variable_prefix_null()) {  
       
   495     /* For code in FUNCTIONs */
       
   496     s4o.print("(*");  
       
   497     symbol->exp->accept(*this);    
       
   498     s4o.print(")");  
       
   499   } else {
       
   500     /* For code in FBs, and PROGRAMS... */
       
   501     if (NULL == dynamic_cast<structured_variable_c *>(symbol->parent)) {
       
   502       s4o.print("(*");  
       
   503       symbol->exp->accept(*this);    
       
   504       s4o.print(")");  
       
   505     } else {
       
   506       /* We are in a structured variable - the structured_variable_c itself will already have printed out the '->' !! */ 
       
   507       if (NULL != dynamic_cast<deref_operator_c *>(symbol->exp))
       
   508         STAGE4_ERROR(symbol, symbol->exp, "The use of consecutive derefencing operators between a struct and its elem (ex: struct_ref_ref^^.elem) is currently not supported for code inside a Function_Block.");
       
   509       symbol->exp->accept(*this);
       
   510     }
       
   511   }
       
   512 
       
   513   return NULL;
       
   514 }
       
   515 
       
   516 
   466 void *visit(deref_expression_c *symbol) {
   517 void *visit(deref_expression_c *symbol) {
   467   s4o.print("(");  
   518   s4o.print("(");  
   468   if (this->is_variable_prefix_null()) {  
   519   if (this->is_variable_prefix_null()) {  
   469     /* For code in FUNCTIONs */
   520     /* For code in FUNCTIONs */
   470     s4o.print("*");  
   521     s4o.print("*");  
   471     symbol->exp->accept(*this);    
   522     symbol->exp->accept(*this);    
   472     s4o.print("");  
   523     s4o.print("");  
   473   } else {
   524   } else {
   474     /* For code in FBs, and PROGRAMS... */
   525     /* For code in FBs, and PROGRAMS... */
   475     s4o.print("(");  
       
   476     unsigned int vartype = analyse_variable_c::first_nonfb_vardecltype(symbol->exp, scope_);
   526     unsigned int vartype = analyse_variable_c::first_nonfb_vardecltype(symbol->exp, scope_);
   477     if (vartype == search_var_instance_decl_c::external_vt) {
   527     if (vartype == search_var_instance_decl_c::external_vt) {
   478       if (!get_datatype_info_c::is_type_valid    (symbol->exp->datatype)) ERROR;
   528       if (!get_datatype_info_c::is_type_valid    (symbol->exp->datatype)) ERROR;
   479       if ( get_datatype_info_c::is_function_block(symbol->exp->datatype))
   529       if ( get_datatype_info_c::is_function_block(symbol->exp->datatype))
   480         s4o.print(GET_EXTERNAL_FB_DREF);
   530         s4o.print(GET_EXTERNAL_FB_DREF);
   494     s4o.print(",");
   544     s4o.print(",");
   495     wanted_variablegeneration = complextype_suffix_vg;
   545     wanted_variablegeneration = complextype_suffix_vg;
   496     symbol->exp->accept(*this);
   546     symbol->exp->accept(*this);
   497     s4o.print(")");
   547     s4o.print(")");
   498     wanted_variablegeneration = old_wanted_variablegeneration;
   548     wanted_variablegeneration = old_wanted_variablegeneration;
   499     
       
   500     s4o.print(")");  
       
   501   }
   549   }
   502   s4o.print(")");  
   550   s4o.print(")");  
   503 
   551 
   504   return NULL;
   552   return NULL;
   505 }
   553 }