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