stage4/generate_c/function_param_iterator.cc
changeset 182 231633d1d2e4
parent 181 38d6eb056260
child 183 fb240c8d1f66
equal deleted inserted replaced
181:38d6eb056260 182:231633d1d2e4
     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     bool en_declared;
       
    94     bool eno_declared;
       
    95 
       
    96   private:
       
    97     void* handle_param_list(list_c *list) {
       
    98       if (next_param <= param_count + list->n)
       
    99         return list->elements[next_param - param_count - 1];
       
   100 
       
   101       /* the desired param is not on this list... */
       
   102       param_count += list->n;
       
   103      return NULL;
       
   104     }
       
   105 
       
   106     void* handle_single_param(symbol_c *var_name) {
       
   107       param_count++;
       
   108       if (next_param == param_count)
       
   109         return var_name;
       
   110 
       
   111       /* not yet the desired param... */
       
   112      return NULL;
       
   113     }
       
   114 
       
   115     void* iterate_list(list_c *list) {
       
   116       void *res;
       
   117       for (int i = 0; i < list->n; i++) {
       
   118         res = list->elements[i]->accept(*this);
       
   119         if (res != NULL)
       
   120 	        return res;
       
   121       }
       
   122       return NULL;
       
   123    }
       
   124 
       
   125 
       
   126   public:
       
   127     /* start off at the first parameter once again... */
       
   128     void reset(void) {
       
   129       next_param = param_count = 0;
       
   130       current_param_name = NULL;
       
   131       current_param_type = current_param_default_value = NULL;
       
   132       en_declared = false;
       
   133       eno_declared = false;
       
   134     }
       
   135 
       
   136     /* initialise the iterator object.
       
   137      * We must be given a reference to the function declaration
       
   138      * that will be analysed...
       
   139      */
       
   140     function_param_iterator_c(function_declaration_c *f_decl) {
       
   141       this->f_decl = f_decl;
       
   142       reset();
       
   143     }
       
   144 
       
   145     /* initialise the iterator object.
       
   146      * We must be given a reference to the function block declaration
       
   147      * that will be analysed...
       
   148      */
       
   149     function_param_iterator_c(function_block_declaration_c *fb_decl) {
       
   150       this->f_decl = fb_decl;
       
   151       reset();
       
   152     }
       
   153 
       
   154     /* initialise the iterator object.
       
   155      * We must be given a reference to the program declaration
       
   156      * that will be analysed...
       
   157      */
       
   158     function_param_iterator_c(program_declaration_c *p_decl) {
       
   159       this->f_decl = p_decl;
       
   160       reset();
       
   161     }
       
   162 
       
   163     /* Skip to the next parameter. After object creation,
       
   164      * the object references on parameter _before_ the first, so
       
   165      * this function must be called once to get the object to
       
   166      * reference the first parameter...
       
   167      *
       
   168      * Returns the parameter's name!
       
   169      */
       
   170     identifier_c *next(void) {
       
   171       void *res;
       
   172       identifier_c *identifier;
       
   173       param_count = 0;
       
   174       next_param++;
       
   175       res = f_decl->accept(*this);
       
   176       if (res != NULL) {
       
   177         symbol_c *sym = (symbol_c *)res;
       
   178         identifier = dynamic_cast<identifier_c *>(sym);
       
   179         if (identifier == NULL)
       
   180           ERROR;
       
   181       }
       
   182       else if (!en_declared) {
       
   183         current_param_direction = direction_in;
       
   184         identifier = declare_en_param();
       
   185       }
       
   186       else if (!eno_declared) {
       
   187         current_param_direction = direction_out;
       
   188         identifier = declare_eno_param();
       
   189       }
       
   190       else
       
   191         return NULL;
       
   192       
       
   193       current_param_name = identifier;
       
   194       return current_param_name;
       
   195     }
       
   196 
       
   197     identifier_c *declare_en_param(void) {
       
   198       en_declared = true;
       
   199       identifier_c *identifier = new identifier_c("EN");
       
   200       current_param_type = (symbol_c*)(new bool_type_name_c());
       
   201       current_param_default_value = (symbol_c*)(new boolean_literal_c(current_param_type, new boolean_true_c()));
       
   202       return identifier;
       
   203     }
       
   204 
       
   205     identifier_c *declare_eno_param(void) {
       
   206       eno_declared = true;
       
   207       identifier_c *identifier = new identifier_c("ENO");
       
   208       current_param_type = (symbol_c*)(new bool_type_name_c());
       
   209       current_param_default_value = NULL;
       
   210       return identifier;
       
   211     }
       
   212 
       
   213     /* Returns the currently referenced parameter's default value,
       
   214      * or NULL if none is specified in the function declrataion itself.
       
   215      */
       
   216     symbol_c *default_value(void) {
       
   217       return current_param_default_value;
       
   218     }
       
   219 
       
   220     /* Returns the currently referenced parameter's type name. */
       
   221     symbol_c *param_type(void) {
       
   222       return current_param_type;
       
   223     }
       
   224 
       
   225     /* Returns the currently referenced parameter's data passing direction.
       
   226      * i.e. VAR_INPUT, VAR_OUTPUT or VAR_INOUT
       
   227      */
       
   228     param_direction_t param_direction(void) {
       
   229       return current_param_direction;
       
   230     }
       
   231 
       
   232 /******************************************/
       
   233 /* B 1.4.3 - Declaration & Initialisation */
       
   234 /******************************************/
       
   235     void *visit(input_declarations_c *symbol) {
       
   236       TRACE("input_declarations_c");
       
   237       current_param_direction = direction_in;
       
   238       return symbol->input_declaration_list->accept(*this);
       
   239     }
       
   240     void *visit(input_declaration_list_c *symbol) {TRACE("input_declaration_list_c"); return iterate_list(symbol);}
       
   241     void *visit(edge_declaration_c *symbol) {TRACE("edge_declaration_c"); return symbol->var1_list->accept(*this);}
       
   242     void *visit(en_param_declaration_c *symbol) {
       
   243       TRACE("en_param_declaration_c");
       
   244       if (en_declared) ERROR;
       
   245       return (void *)declare_en_param();
       
   246     }
       
   247 
       
   248     /* var1_list ':' array_spec_init */
       
   249     //SYM_REF2(array_var_init_decl_c, var1_list, array_spec_init)
       
   250     void *visit(array_var_init_decl_c *symbol) {TRACE("array_var_init_decl_c"); return symbol->var1_list->accept(*this);}
       
   251     
       
   252     /*  var1_list ':' initialized_structure */
       
   253     //SYM_REF2(structured_var_init_decl_c, var1_list, initialized_structure)
       
   254     void *visit(structured_var_init_decl_c *symbol) {TRACE("structured_var_init_decl_c"); return symbol->var1_list->accept(*this);}
       
   255     
       
   256 #if 0
       
   257 /* name_list ':' function_block_type_name ASSIGN structure_initialization */
       
   258 /* structure_initialization -> may be NULL ! */
       
   259 SYM_REF4(fb_name_decl_c, fb_name_list, function_block_type_name, structure_initialization, unused)
       
   260 
       
   261 /* name_list ',' fb_name */
       
   262 SYM_LIST(fb_name_list_c)
       
   263 #endif
       
   264 
       
   265     void *visit(output_declarations_c *symbol) {
       
   266       TRACE("output_declarations_c");
       
   267       current_param_direction = direction_out;
       
   268       return symbol->var_init_decl_list->accept(*this);
       
   269     }
       
   270     void *visit(eno_param_declaration_c *symbol) {
       
   271       TRACE("eno_param_declaration_c");
       
   272       if (eno_declared) ERROR;
       
   273       return (void *)declare_eno_param();
       
   274     }
       
   275     void *visit(input_output_declarations_c *symbol) {
       
   276       TRACE("input_output_declarations_c");
       
   277       current_param_direction = direction_inout;
       
   278       return symbol->var_declaration_list->accept(*this);
       
   279     }
       
   280     void *visit(var_declaration_list_c *symbol) {TRACE("var_declaration_list_c"); return iterate_list(symbol);}
       
   281 
       
   282 
       
   283     /*  var1_list ':' array_specification */
       
   284     //SYM_REF2(array_var_declaration_c, var1_list, array_specification)
       
   285     void *visit(array_var_declaration_c *symbol) {TRACE("array_var_declaration_c"); return symbol->var1_list->accept(*this);}
       
   286 
       
   287     /*  var1_list ':' structure_type_name */
       
   288     //SYM_REF2(structured_var_declaration_c, var1_list, structure_type_name)
       
   289     void *visit(structured_var_declaration_c *symbol) {TRACE("structured_var_declaration_c"); return symbol->var1_list->accept(*this);}
       
   290 
       
   291     /* VAR [CONSTANT] var_init_decl_list END_VAR */
       
   292     void *visit(var_declarations_c *symbol) {TRACE("var_declarations_c"); return NULL;}
       
   293 
       
   294 #if 0
       
   295 /*  VAR RETAIN var_init_decl_list END_VAR */
       
   296 SYM_REF2(retentive_var_declarations_c, var_init_decl_list, unused)
       
   297 
       
   298 /*  VAR [CONSTANT|RETAIN|NON_RETAIN] located_var_decl_list END_VAR */
       
   299 /* option -> may be NULL ! */
       
   300 SYM_REF2(located_var_declarations_c, option, located_var_decl_list)
       
   301 
       
   302 /* helper symbol for located_var_declarations */
       
   303 /* located_var_decl_list located_var_decl ';' */
       
   304 SYM_LIST(located_var_decl_list_c)
       
   305 
       
   306 /*  [variable_name] location ':' located_var_spec_init */
       
   307 /* variable_name -> may be NULL ! */
       
   308 SYM_REF4(located_var_decl_c, variable_name, location, located_var_spec_init, unused)
       
   309 #endif
       
   310 
       
   311 /*| VAR_EXTERNAL [CONSTANT] external_declaration_list END_VAR */
       
   312 /* option -> may be NULL ! */
       
   313 // SYM_REF2(external_var_declarations_c, option, external_declaration_list)
       
   314     void *visit(external_var_declarations_c *symbol) {
       
   315       TRACE("external_var_declarations_c");
       
   316       current_param_direction = direction_extref;
       
   317       return symbol->external_declaration_list->accept(*this);
       
   318     }
       
   319 
       
   320 /* helper symbol for external_var_declarations */
       
   321 /*| external_declaration_list external_declaration';' */
       
   322 // SYM_LIST(external_declaration_list_c)
       
   323     void *visit(external_declaration_list_c *symbol) {TRACE("external_declaration_list_c"); return iterate_list(symbol);}
       
   324 
       
   325 /*  global_var_name ':' (simple_specification|subrange_specification|enumerated_specification|array_specification|prev_declared_structure_type_name|function_block_type_name */
       
   326 //SYM_REF2(external_declaration_c, global_var_name, specification)
       
   327     void *visit(external_declaration_c *symbol) {
       
   328       TRACE("external_declaration_c");
       
   329       /* It is OK to store these values in the current_param_XXX
       
   330        * variables, because if the desired parameter is not in the
       
   331        * variable list we will be analysing, the current_param_XXXX
       
   332        * variables will get overwritten when we visit the next
       
   333        * var1_init_decl_c list!
       
   334        */
       
   335       current_param_default_value = spec_init_sperator_c::get_init(symbol->specification);
       
   336       current_param_type = spec_init_sperator_c::get_spec(symbol->specification);
       
   337 
       
   338       return handle_single_param(symbol->global_var_name);
       
   339     }
       
   340 
       
   341 
       
   342 #if 0
       
   343 /*| VAR_GLOBAL [CONSTANT|RETAIN] global_var_decl_list END_VAR */
       
   344 /* option -> may be NULL ! */
       
   345 SYM_REF2(global_var_declarations_c, option, global_var_decl_list)
       
   346 
       
   347 /* helper symbol for global_var_declarations */
       
   348 /*| global_var_decl_list global_var_decl ';' */
       
   349 SYM_LIST(global_var_decl_list_c)
       
   350 
       
   351 /*| global_var_spec ':' [located_var_spec_init|function_block_type_name] */
       
   352 /* type_specification ->may be NULL ! */
       
   353 SYM_REF2(global_var_decl_c, global_var_spec, type_specification)
       
   354 
       
   355 /*| global_var_name location */
       
   356 SYM_REF2(global_var_spec_c, global_var_name, location)
       
   357 
       
   358 /*  AT direct_variable */
       
   359 SYM_REF2(location_c, direct_variable, unused)
       
   360 
       
   361 /*| global_var_list ',' global_var_name */
       
   362 SYM_LIST(global_var_list_c)
       
   363 
       
   364 /*  var1_list ':' single_byte_string_spec */
       
   365 SYM_REF2(single_byte_string_var_declaration_c, var1_list, single_byte_string_spec)
       
   366 
       
   367 /*  STRING ['[' integer ']'] [ASSIGN single_byte_character_string] */
       
   368 /* integer ->may be NULL ! */
       
   369 /* single_byte_character_string ->may be NULL ! */
       
   370 SYM_REF2(single_byte_string_spec_c, integer, single_byte_character_string)
       
   371 
       
   372 /*  var1_list ':' double_byte_string_spec */
       
   373 SYM_REF2(double_byte_string_var_declaration_c, var1_list, double_byte_string_spec)
       
   374 
       
   375 /*  WSTRING ['[' integer ']'] [ASSIGN double_byte_character_string] */
       
   376 /* integer ->may be NULL ! */
       
   377 /* double_byte_character_string ->may be NULL ! */
       
   378 SYM_REF2(double_byte_string_spec_c, integer, double_byte_character_string)
       
   379 
       
   380 /*| VAR [RETAIN|NON_RETAIN] incompl_located_var_decl_list END_VAR */
       
   381 /* option ->may be NULL ! */
       
   382 SYM_REF2(incompl_located_var_declarations_c, option, incompl_located_var_decl_list)
       
   383 
       
   384 /* helper symbol for incompl_located_var_declarations */
       
   385 /*| incompl_located_var_decl_list incompl_located_var_decl ';' */
       
   386 SYM_LIST(incompl_located_var_decl_list_c)
       
   387 
       
   388 /*  variable_name incompl_location ':' var_spec */
       
   389 SYM_REF4(incompl_located_var_decl_c, variable_name, incompl_location, var_spec, unused)
       
   390 
       
   391 /*  AT incompl_location_token */
       
   392 SYM_TOKEN(incompl_location_c)
       
   393 #endif
       
   394 
       
   395 
       
   396     void *visit(var1_init_decl_c *symbol) {
       
   397       TRACE("var1_init_decl_c");
       
   398       /* It is OK to store these values in the current_param_XXX
       
   399        * variables, because if the desired parameter is not in the
       
   400        * variable list we will be analysing, the current_param_XXXX
       
   401        * variables will get overwritten when we visit the next
       
   402        * var1_init_decl_c list!
       
   403        */
       
   404       current_param_default_value = spec_init_sperator_c::get_init(symbol->spec_init);
       
   405       current_param_type = spec_init_sperator_c::get_spec(symbol->spec_init);
       
   406 
       
   407       return symbol->var1_list->accept(*this);
       
   408     }
       
   409 
       
   410 
       
   411 
       
   412     void *visit(var1_list_c *symbol) {
       
   413       TRACE("var1_list_c");
       
   414       return handle_param_list(symbol);
       
   415     }
       
   416 
       
   417     void *visit(var_init_decl_list_c *symbol) {TRACE("var_init_decl_list_c"); return iterate_list(symbol);}
       
   418 
       
   419 
       
   420 /***********************/
       
   421 /* B 1.5.1 - Functions */
       
   422 /***********************/
       
   423     void *visit(function_declaration_c *symbol) {TRACE("function_declaration_c"); return symbol->var_declarations_list->accept(*this);}
       
   424     /* intermediate helper symbol for function_declaration */
       
   425     void *visit(var_declarations_list_c *symbol) {TRACE("var_declarations_list_c"); return iterate_list(symbol);}
       
   426     void *visit(function_var_decls_c *symbol) {TRACE("function_var_decls_c"); /* ignore */ return NULL;}
       
   427 
       
   428 
       
   429 /*****************************/
       
   430 /* B 1.5.2 - Function Blocks */
       
   431 /*****************************/
       
   432 /*  FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations function_block_body END_FUNCTION_BLOCK */
       
   433     void *visit(function_block_declaration_c *symbol) {TRACE("function_block_declaration_c"); return symbol->var_declarations->accept(*this);}
       
   434 
       
   435 /* intermediate helper symbol for function_declaration */
       
   436 /*  { io_var_declarations | other_var_declarations }   */
       
   437 /*
       
   438  * NOTE: we re-use the var_declarations_list_c
       
   439  */
       
   440 
       
   441 /*  VAR_TEMP temp_var_decl_list END_VAR */
       
   442     void *visit(temp_var_decls_c *symbol) {TRACE("temp_var_decls_c"); /* ignore */ return NULL;}
       
   443     void *visit(temp_var_decls_list_c *symbol) {TRACE("temp_var_decls_list_c"); /* ignore */ return NULL;}
       
   444 
       
   445 /*  VAR NON_RETAIN var_init_decl_list END_VAR */
       
   446     void *visit(non_retentive_var_decls_c *symbol) {TRACE("non_retentive_var_decls_c"); /* ignore */ return NULL;}
       
   447 
       
   448 
       
   449 /**********************/
       
   450 /* B 1.5.3 - Programs */
       
   451 /**********************/
       
   452 /*  PROGRAM program_type_name program_var_declarations_list function_block_body END_PROGRAM */
       
   453 // SYM_REF4(program_declaration_c, program_type_name, var_declarations, function_block_body, unused)
       
   454     void *visit(program_declaration_c *symbol) {TRACE("program_declaration_c"); return symbol->var_declarations->accept(*this);}
       
   455 
       
   456 /* intermediate helper symbol for program_declaration_c */
       
   457 /*  { io_var_declarations | other_var_declarations }   */
       
   458 /*
       
   459  * NOTE: we re-use the var_declarations_list_c
       
   460  */
       
   461 
       
   462 };
       
   463 
       
   464 
       
   465 
       
   466 
       
   467 
       
   468 
       
   469