stage4/generate_c/function_param_iterator.cc
changeset 70 e1f0ebd2d9ec
child 146 eef5e62048c7
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  * Function parameter iterator.
       
    28  * Iterate through the in/out parameters of a function declaration.
       
    29  * Function blocks are also suported.
       
    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 
       
    40 
       
    41 //#include <stdio.h>  /* required for NULL */
       
    42 //#include <string>
       
    43 //#include <iostream>
       
    44 
       
    45 //#include "../../util/symtable.hh"
       
    46 
       
    47 //#include "generate_c.hh"
       
    48 
       
    49 
       
    50 #include "../../absyntax/visitor.hh"
       
    51 
       
    52 
       
    53 /* given a function_declaration_c, iterate through each
       
    54  * function in/out/inout parameter, returning the name
       
    55  * of each parameter...function_param_iterator_c
       
    56  */
       
    57 class function_param_iterator_c : public null_visitor_c {
       
    58   public:
       
    59     /* A type to specify the type of parameter.
       
    60      * VAR_INPUT => direction_in
       
    61      * VAR_OUTPUT => direction_out
       
    62      * VAR_IN_OUT => direction_inout
       
    63      * VAR_EXTERNAL => direction_extref
       
    64      *
       
    65      * Note that VAR_EXTERNAL declares variables that are in reality references
       
    66      * to global variables. This is used only inside programs!
       
    67      * These references to external variables must be correctly initialised to refer
       
    68      * to the correct global variable. Note that the user may define which variable is to be
       
    69      * referenced in a CONFIGURATION, and that different instantiations of a program
       
    70      * may have the same external variable reference diffenrent global variables!
       
    71      * The references must therefore be correctly initialised when the program instance
       
    72      * is created. This may be done by the PROGRAM class constructor since the ST and IL
       
    73      * languages do not allow the VAR_EXTERNAL reference to change at runtime
       
    74      * for a specific instance.
       
    75      *
       
    76      * We therefore need to call a PROGRAM class constructor with the variables
       
    77      * that should be refernced by the VAR_EXTERNAL variables. The direction_extref will
       
    78      * be used to identify these parameters!
       
    79      */
       
    80     typedef enum {direction_in, direction_out, direction_inout, direction_extref} param_direction_t ;
       
    81 
       
    82 
       
    83   private:
       
    84       /* a pointer to the function_block_declaration_c
       
    85        * or function_declaration_c currently being analysed.
       
    86        */
       
    87     symbol_c *f_decl;
       
    88     int next_param, param_count;
       
    89     identifier_c *current_param_name;
       
    90     symbol_c *current_param_type;
       
    91     symbol_c *current_param_default_value;
       
    92     param_direction_t current_param_direction;
       
    93 
       
    94   private:
       
    95     void* handle_param_list(list_c *list) {
       
    96       if (next_param <= param_count + list->n)
       
    97         return list->elements[next_param - param_count - 1];
       
    98 
       
    99       /* the desired param is not on this list... */
       
   100       param_count += list->n;
       
   101      return NULL;
       
   102     }
       
   103 
       
   104     void* handle_single_param(symbol_c *var_name) {
       
   105       param_count++;
       
   106       if (next_param == param_count)
       
   107         return var_name;
       
   108 
       
   109       /* not yet the desired param... */
       
   110      return NULL;
       
   111     }
       
   112 
       
   113     void* iterate_list(list_c *list) {
       
   114       void *res;
       
   115       for (int i = 0; i < list->n; i++) {
       
   116         res = list->elements[i]->accept(*this);
       
   117 	if (res != NULL)
       
   118 	  return res;
       
   119       }
       
   120       return NULL;
       
   121    }
       
   122 
       
   123 
       
   124   public:
       
   125     /* start off at the first parameter once again... */
       
   126     void reset(void) {
       
   127       next_param = param_count = 0;
       
   128       current_param_name = NULL;
       
   129       current_param_type = current_param_default_value = NULL;
       
   130     }
       
   131 
       
   132     /* initialise the iterator object.
       
   133      * We must be given a reference to the function declaration
       
   134      * that will be analysed...
       
   135      */
       
   136     function_param_iterator_c(function_declaration_c *f_decl) {
       
   137       this->f_decl = f_decl;
       
   138       reset();
       
   139     }
       
   140 
       
   141     /* initialise the iterator object.
       
   142      * We must be given a reference to the function block declaration
       
   143      * that will be analysed...
       
   144      */
       
   145     function_param_iterator_c(function_block_declaration_c *fb_decl) {
       
   146       this->f_decl = fb_decl;
       
   147       reset();
       
   148     }
       
   149 
       
   150     /* initialise the iterator object.
       
   151      * We must be given a reference to the program declaration
       
   152      * that will be analysed...
       
   153      */
       
   154     function_param_iterator_c(program_declaration_c *p_decl) {
       
   155       this->f_decl = p_decl;
       
   156       reset();
       
   157     }
       
   158 
       
   159     /* Skip to the next parameter. After object creation,
       
   160      * the object references on parameter _before_ the first, so
       
   161      * this function must be called once to get the object to
       
   162      * reference the first parameter...
       
   163      *
       
   164      * Returns the parameter's name!
       
   165      */
       
   166     identifier_c *next(void) {
       
   167       void *res;
       
   168       param_count = 0;
       
   169       next_param++;
       
   170       res = f_decl->accept(*this);
       
   171       if (res == NULL)
       
   172         return NULL;
       
   173 
       
   174       symbol_c *sym = (symbol_c *)res;
       
   175       identifier_c *identifier = dynamic_cast<identifier_c *>(sym);
       
   176       if (identifier == NULL)
       
   177         ERROR;
       
   178 
       
   179       current_param_name = identifier;
       
   180       return current_param_name;
       
   181     }
       
   182 
       
   183     /* Returns the currently referenced parameter's default value,
       
   184      * or NULL if none is specified in the function declrataion itself.
       
   185      */
       
   186     symbol_c *default_value(void) {
       
   187       return current_param_default_value;
       
   188     }
       
   189 
       
   190     /* Returns the currently referenced parameter's type name. */
       
   191     symbol_c *param_type(void) {
       
   192       return current_param_type;
       
   193     }
       
   194 
       
   195     /* Returns the currently referenced parameter's data passing direction.
       
   196      * i.e. VAR_INPUT, VAR_OUTPUT or VAR_INOUT
       
   197      */
       
   198     param_direction_t param_direction(void) {
       
   199       return current_param_direction;
       
   200     }
       
   201 
       
   202 /******************************************/
       
   203 /* B 1.4.3 - Declaration & Initialisation */
       
   204 /******************************************/
       
   205     void *visit(input_declarations_c *symbol) {
       
   206       TRACE("input_declarations_c");
       
   207       current_param_direction = direction_in;
       
   208       return symbol->input_declaration_list->accept(*this);
       
   209     }
       
   210     void *visit(input_declaration_list_c *symbol) {TRACE("input_declaration_list_c"); return iterate_list(symbol);}
       
   211     void *visit(edge_declaration_c *symbol) {TRACE("edge_declaration_c"); return symbol->var1_list->accept(*this);}
       
   212 
       
   213 #if 0
       
   214 /* var1_list ':' array_spec_init */
       
   215 SYM_REF2(array_var_init_decl_c, var1_list, array_spec_init)
       
   216 
       
   217 /*  var1_list ':' initialized_structure */
       
   218 SYM_REF2(structured_var_init_decl_c, var1_list, initialized_structure)
       
   219 
       
   220 /* name_list ':' function_block_type_name ASSIGN structure_initialization */
       
   221 /* structure_initialization -> may be NULL ! */
       
   222 SYM_REF4(fb_name_decl_c, fb_name_list, function_block_type_name, structure_initialization, unused)
       
   223 
       
   224 /* name_list ',' fb_name */
       
   225 SYM_LIST(fb_name_list_c)
       
   226 #endif
       
   227 
       
   228     void *visit(output_declarations_c *symbol) {
       
   229       TRACE("output_declarations_c");
       
   230       current_param_direction = direction_out;
       
   231       return symbol->var_init_decl_list->accept(*this);
       
   232     }
       
   233     void *visit(input_output_declarations_c *symbol) {
       
   234       TRACE("input_output_declarations_c");
       
   235       current_param_direction = direction_inout;
       
   236       return symbol->var_declaration_list->accept(*this);
       
   237     }
       
   238     void *visit(var_declaration_list_c *symbol) {TRACE("var_declaration_list_c"); return iterate_list(symbol);}
       
   239 
       
   240 #if 0
       
   241 /*  var1_list ':' array_specification */
       
   242 SYM_REF2(array_var_declaration_c, var1_list, array_specification)
       
   243 
       
   244 /*  var1_list ':' structure_type_name */
       
   245 SYM_REF2(structured_var_declaration_c, var1_list, structure_type_name)
       
   246 #endif
       
   247 
       
   248 /* VAR [CONSTANT] var_init_decl_list END_VAR */
       
   249     void *visit(var_declarations_c *symbol) {TRACE("var_declarations_c"); return NULL;}
       
   250 
       
   251 #if 0
       
   252 /*  VAR RETAIN var_init_decl_list END_VAR */
       
   253 SYM_REF2(retentive_var_declarations_c, var_init_decl_list, unused)
       
   254 
       
   255 /*  VAR [CONSTANT|RETAIN|NON_RETAIN] located_var_decl_list END_VAR */
       
   256 /* option -> may be NULL ! */
       
   257 SYM_REF2(located_var_declarations_c, option, located_var_decl_list)
       
   258 
       
   259 /* helper symbol for located_var_declarations */
       
   260 /* located_var_decl_list located_var_decl ';' */
       
   261 SYM_LIST(located_var_decl_list_c)
       
   262 
       
   263 /*  [variable_name] location ':' located_var_spec_init */
       
   264 /* variable_name -> may be NULL ! */
       
   265 SYM_REF4(located_var_decl_c, variable_name, location, located_var_spec_init, unused)
       
   266 #endif
       
   267 
       
   268 /*| VAR_EXTERNAL [CONSTANT] external_declaration_list END_VAR */
       
   269 /* option -> may be NULL ! */
       
   270 // SYM_REF2(external_var_declarations_c, option, external_declaration_list)
       
   271     void *visit(external_var_declarations_c *symbol) {
       
   272       TRACE("external_var_declarations_c");
       
   273       current_param_direction = direction_extref;
       
   274       return symbol->external_declaration_list->accept(*this);
       
   275     }
       
   276 
       
   277 /* helper symbol for external_var_declarations */
       
   278 /*| external_declaration_list external_declaration';' */
       
   279 // SYM_LIST(external_declaration_list_c)
       
   280     void *visit(external_declaration_list_c *symbol) {TRACE("external_declaration_list_c"); return iterate_list(symbol);}
       
   281 
       
   282 /*  global_var_name ':' (simple_specification|subrange_specification|enumerated_specification|array_specification|prev_declared_structure_type_name|function_block_type_name */
       
   283 //SYM_REF2(external_declaration_c, global_var_name, specification)
       
   284     void *visit(external_declaration_c *symbol) {
       
   285       TRACE("external_declaration_c");
       
   286       /* It is OK to store these values in the current_param_XXX
       
   287        * variables, because if the desired parameter is not in the
       
   288        * variable list we will be analysing, the current_param_XXXX
       
   289        * variables will get overwritten when we visit the next
       
   290        * var1_init_decl_c list!
       
   291        */
       
   292       current_param_default_value = spec_init_sperator_c::get_init(symbol->specification);
       
   293       current_param_type = spec_init_sperator_c::get_spec(symbol->specification);
       
   294 
       
   295       return handle_single_param(symbol->global_var_name);
       
   296     }
       
   297 
       
   298 
       
   299 #if 0
       
   300 /*| VAR_GLOBAL [CONSTANT|RETAIN] global_var_decl_list END_VAR */
       
   301 /* option -> may be NULL ! */
       
   302 SYM_REF2(global_var_declarations_c, option, global_var_decl_list)
       
   303 
       
   304 /* helper symbol for global_var_declarations */
       
   305 /*| global_var_decl_list global_var_decl ';' */
       
   306 SYM_LIST(global_var_decl_list_c)
       
   307 
       
   308 /*| global_var_spec ':' [located_var_spec_init|function_block_type_name] */
       
   309 /* type_specification ->may be NULL ! */
       
   310 SYM_REF2(global_var_decl_c, global_var_spec, type_specification)
       
   311 
       
   312 /*| global_var_name location */
       
   313 SYM_REF2(global_var_spec_c, global_var_name, location)
       
   314 
       
   315 /*  AT direct_variable */
       
   316 SYM_REF2(location_c, direct_variable, unused)
       
   317 
       
   318 /*| global_var_list ',' global_var_name */
       
   319 SYM_LIST(global_var_list_c)
       
   320 
       
   321 /*  var1_list ':' single_byte_string_spec */
       
   322 SYM_REF2(single_byte_string_var_declaration_c, var1_list, single_byte_string_spec)
       
   323 
       
   324 /*  STRING ['[' integer ']'] [ASSIGN single_byte_character_string] */
       
   325 /* integer ->may be NULL ! */
       
   326 /* single_byte_character_string ->may be NULL ! */
       
   327 SYM_REF2(single_byte_string_spec_c, integer, single_byte_character_string)
       
   328 
       
   329 /*  var1_list ':' double_byte_string_spec */
       
   330 SYM_REF2(double_byte_string_var_declaration_c, var1_list, double_byte_string_spec)
       
   331 
       
   332 /*  WSTRING ['[' integer ']'] [ASSIGN double_byte_character_string] */
       
   333 /* integer ->may be NULL ! */
       
   334 /* double_byte_character_string ->may be NULL ! */
       
   335 SYM_REF2(double_byte_string_spec_c, integer, double_byte_character_string)
       
   336 
       
   337 /*| VAR [RETAIN|NON_RETAIN] incompl_located_var_decl_list END_VAR */
       
   338 /* option ->may be NULL ! */
       
   339 SYM_REF2(incompl_located_var_declarations_c, option, incompl_located_var_decl_list)
       
   340 
       
   341 /* helper symbol for incompl_located_var_declarations */
       
   342 /*| incompl_located_var_decl_list incompl_located_var_decl ';' */
       
   343 SYM_LIST(incompl_located_var_decl_list_c)
       
   344 
       
   345 /*  variable_name incompl_location ':' var_spec */
       
   346 SYM_REF4(incompl_located_var_decl_c, variable_name, incompl_location, var_spec, unused)
       
   347 
       
   348 /*  AT incompl_location_token */
       
   349 SYM_TOKEN(incompl_location_c)
       
   350 #endif
       
   351 
       
   352 
       
   353     void *visit(var1_init_decl_c *symbol) {
       
   354       TRACE("var1_init_decl_c");
       
   355       /* It is OK to store these values in the current_param_XXX
       
   356        * variables, because if the desired parameter is not in the
       
   357        * variable list we will be analysing, the current_param_XXXX
       
   358        * variables will get overwritten when we visit the next
       
   359        * var1_init_decl_c list!
       
   360        */
       
   361       current_param_default_value = spec_init_sperator_c::get_init(symbol->spec_init);
       
   362       current_param_type = spec_init_sperator_c::get_spec(symbol->spec_init);
       
   363 
       
   364       return symbol->var1_list->accept(*this);
       
   365     }
       
   366 
       
   367 
       
   368 
       
   369     void *visit(var1_list_c *symbol) {
       
   370       TRACE("var1_list_c");
       
   371       return handle_param_list(symbol);
       
   372     }
       
   373 
       
   374     void *visit(var_init_decl_list_c *symbol) {TRACE("var_init_decl_list_c"); return iterate_list(symbol);}
       
   375 
       
   376 
       
   377 /***********************/
       
   378 /* B 1.5.1 - Functions */
       
   379 /***********************/
       
   380     void *visit(function_declaration_c *symbol) {TRACE("function_declaration_c"); return symbol->var_declarations_list->accept(*this);}
       
   381     /* intermediate helper symbol for function_declaration */
       
   382     void *visit(var_declarations_list_c *symbol) {TRACE("var_declarations_list_c"); return iterate_list(symbol);}
       
   383     void *visit(function_var_decls_c *symbol) {TRACE("function_var_decls_c"); /* ignore */ return NULL;}
       
   384 
       
   385 
       
   386 /*****************************/
       
   387 /* B 1.5.2 - Function Blocks */
       
   388 /*****************************/
       
   389 /*  FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations function_block_body END_FUNCTION_BLOCK */
       
   390     void *visit(function_block_declaration_c *symbol) {TRACE("function_block_declaration_c"); return symbol->var_declarations->accept(*this);}
       
   391 
       
   392 /* intermediate helper symbol for function_declaration */
       
   393 /*  { io_var_declarations | other_var_declarations }   */
       
   394 /*
       
   395  * NOTE: we re-use the var_declarations_list_c
       
   396  */
       
   397 
       
   398 /*  VAR_TEMP temp_var_decl_list END_VAR */
       
   399     void *visit(temp_var_decls_c *symbol) {TRACE("temp_var_decls_c"); /* ignore */ return NULL;}
       
   400     void *visit(temp_var_decls_list_c *symbol) {TRACE("temp_var_decls_list_c"); /* ignore */ return NULL;}
       
   401 
       
   402 /*  VAR NON_RETAIN var_init_decl_list END_VAR */
       
   403     void *visit(non_retentive_var_decls_c *symbol) {TRACE("non_retentive_var_decls_c"); /* ignore */ return NULL;}
       
   404 
       
   405 
       
   406 /**********************/
       
   407 /* B 1.5.3 - Programs */
       
   408 /**********************/
       
   409 /*  PROGRAM program_type_name program_var_declarations_list function_block_body END_PROGRAM */
       
   410 // SYM_REF4(program_declaration_c, program_type_name, var_declarations, function_block_body, unused)
       
   411     void *visit(program_declaration_c *symbol) {TRACE("program_declaration_c"); return symbol->var_declarations->accept(*this);}
       
   412 
       
   413 /* intermediate helper symbol for program_declaration_c */
       
   414 /*  { io_var_declarations | other_var_declarations }   */
       
   415 /*
       
   416  * NOTE: we re-use the var_declarations_list_c
       
   417  */
       
   418 
       
   419 };
       
   420 
       
   421 
       
   422 
       
   423 
       
   424 
       
   425 
       
   426