stage4/generate_cc/generate_cc_tempvardecl.cc
changeset 70 e1f0ebd2d9ec
parent 69 41cb5b80416e
child 71 c2c867171c07
equal deleted inserted replaced
69:41cb5b80416e 70:e1f0ebd2d9ec
     1 /*
       
     2  * (c) 2003 Mario de Sousa
       
     3  *
       
     4  * Offered to the public under the terms of the GNU General Public License
       
     5  * as published by the Free Software Foundation; either version 2 of the
       
     6  * License, or (at your option) any later version.
       
     7  *
       
     8  * This program is distributed in the hope that it will be useful, but
       
     9  * WITHOUT ANY WARRANTY; without even the implied warranty of
       
    10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
       
    11  * Public License for more details.
       
    12  *
       
    13  * This code is made available on the understanding that it will not be
       
    14  * used in safety-critical situations without a full and competent review.
       
    15  */
       
    16 
       
    17 /*
       
    18  * An IEC 61131-3 IL and ST compiler.
       
    19  *
       
    20  * Based on the
       
    21  * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
       
    22  *
       
    23  */
       
    24 
       
    25 
       
    26 /*
       
    27  * Declare temporary variables to be later used as output parameters
       
    28  * in function calls for which not all output parameters were
       
    29  * defined in the original (st or il) source code.
       
    30  *
       
    31  * This is part of the 4th stage that generates
       
    32  * a c++ source program equivalent to the IL and ST
       
    33  * code.
       
    34  */
       
    35 
       
    36 
       
    37 
       
    38 
       
    39 class temp_var_name_c {
       
    40   private:
       
    41     int counter;
       
    42 
       
    43   public:
       
    44     void reset(void) {counter = 0;}
       
    45     temp_var_name_c(void) {reset();}
       
    46 
       
    47   public:
       
    48     std::string *new_name(void) {
       
    49       std::string *new_str = new std::string(TEMP_VAR);
       
    50       /* yikes!!! How to convert an int to a string elegantly???
       
    51        * Right now I (Mario) can only think of snprintf()
       
    52        * C++ must have a more elegant method!
       
    53        */
       
    54       int int_str_size = snprintf(NULL, 0, "%d", counter);
       
    55       if (int_str_size <= 0) ERROR;
       
    56       char *int_str = (char *)malloc(int_str_size+1);
       
    57       if (snprintf(int_str, int_str_size+1, "%d", counter++) >= int_str_size+1) ERROR;
       
    58       *new_str += int_str;
       
    59       free(int_str);
       
    60       return new_str;
       
    61     }
       
    62 
       
    63 };
       
    64 
       
    65 
       
    66 
       
    67 /***********************************************************************/
       
    68 /***********************************************************************/
       
    69 /***********************************************************************/
       
    70 /***********************************************************************/
       
    71 
       
    72 
       
    73 
       
    74 /* Some function calls in the body of functions or function blocks
       
    75  * may leave some parameters to their default values, and
       
    76  * ignore some output parameters of the function being called.
       
    77  * Our conversion of ST functions to C++ does not contemplate that,
       
    78  * i.e. each called function must get all it's input and output
       
    79  * parameters set correctly.
       
    80  * For input parameters we merely need to call the function with
       
    81  * the apropriate default value, but for output parameters
       
    82  * we must create temporary variables to hold the output value.
       
    83  *
       
    84  * We declare all the temporary output variables at the begining of
       
    85  * the body of each function or function block, and use them as
       
    86  * in function calls later on as they become necessary...
       
    87  * Note that we cannot create these variables just before a function
       
    88  * call, as the function call itself may be integrated within an
       
    89  * expression, or another function call!
       
    90  *
       
    91  * The variables are declared in the exact same order in which they
       
    92  * will be used later on during the function calls, which allows us
       
    93  * to simply re-create the name that was used for the temporary variable
       
    94  * instead of keeping it in some list.
       
    95  * The names are recreated by the temp_var_name_factory, after reset()
       
    96  * has been called!
       
    97  *
       
    98  * This function will genertae code similar to...
       
    99  *
       
   100  *     INT __TMP_0 = 23;
       
   101  *     REAL __TMP_1 = 45.5;
       
   102  *     ...
       
   103  */
       
   104 
       
   105 class generate_cc_tempvardecl_c: generate_cc_typedecl_c {
       
   106   public:
       
   107     generate_cc_tempvardecl_c(stage4out_c *s4o_ptr): generate_cc_typedecl_c(s4o_ptr) {}
       
   108 
       
   109     void generate(symbol_c *body, temp_var_name_c *temp_var_name_factory) {
       
   110       temp_var_name_factory->reset();
       
   111       function_call_iterator_c fcall_iterator(body);
       
   112       for(symbol_c *finvocation = NULL; (finvocation = fcall_iterator.next()) != NULL;) {
       
   113         /* get the name of the next function that gets called */
       
   114         identifier_c *fcalled_name = fcall_iterator.fname();
       
   115         /* get that function's declaration... */
       
   116         function_declaration_c *fdecl = function_symtable.find_value(fcalled_name);
       
   117         if (fdecl == function_symtable.end_value()) {
       
   118           function_type_t function_type = get_function_type(fcalled_name);
       
   119           if (function_type == function_none) ERROR;
       
   120           return;
       
   121         }
       
   122         /* create iterator to iterate through each of the called function's parameters... */
       
   123         function_param_iterator_c fp_iterator(fdecl);
       
   124 
       
   125         /* iterate through each of the called function's parameters... */
       
   126         identifier_c *param_name = NULL;
       
   127         function_call_param_iterator_c function_call_param_iterator(finvocation);
       
   128         for(int i = 1; (param_name = fp_iterator.next()) != NULL; i++) {
       
   129 
       
   130           function_param_iterator_c::param_direction_t param_direction = fp_iterator.param_direction();
       
   131           if (param_direction == function_param_iterator_c::direction_in)
       
   132             /* ignore input only parameters...
       
   133              * we do not need to create temporary variables for these!
       
   134              */
       
   135             continue;
       
   136 
       
   137           /* Get the value from a foo(<param_name> = <param_value>) style call */
       
   138           symbol_c *param_value = function_call_param_iterator.search(param_name);
       
   139 
       
   140           /* Get the value from a foo(<param_value>) style call */
       
   141           if (param_value == NULL)
       
   142             param_value = function_call_param_iterator.next();
       
   143 
       
   144           if (param_value != NULL)
       
   145             /* ignore output parameters to which a variable is passed...
       
   146              * we do not need to create temporary variables for these!
       
   147              */
       
   148             continue;
       
   149 
       
   150           symbol_c *param_type = fp_iterator.param_type();
       
   151 
       
   152           /* get the parameter's default value */
       
   153           param_value = fp_iterator.default_value();
       
   154 
       
   155           /* If no default value specified in function declaration,
       
   156            * get the default value of this variable's type
       
   157            */
       
   158           if (param_value == NULL)
       
   159             param_value = (symbol_c *)param_type->accept(*type_initial_value_c::instance());
       
   160           if (param_value == NULL) ERROR;
       
   161 
       
   162           /* now declare a temporary variable, with the correct default value... */
       
   163           s4o.print(s4o.indent_spaces);
       
   164           param_type->accept(*this);
       
   165           s4o.print(" ");
       
   166 
       
   167           std::string *temp_var_name = temp_var_name_factory->new_name();
       
   168           s4o.print(*temp_var_name);
       
   169           delete temp_var_name;
       
   170 
       
   171           s4o.print(" = ");
       
   172           param_value->accept(*this);
       
   173           s4o.print(";\n");
       
   174         }
       
   175       }
       
   176       temp_var_name_factory->reset();
       
   177       s4o.print("\n");
       
   178     }
       
   179 };