--- a/stage3/constant_folding.cc Thu Dec 25 08:40:15 2014 +0000
+++ b/stage3/constant_folding.cc Fri Dec 26 08:09:34 2014 +0000
@@ -235,9 +235,6 @@
}\
}
-typedef std::map <std::string, const_value_c> map_values_t;
-
-static map_values_t values;
@@ -726,9 +723,9 @@
return NULL;
}
-static map_values_t inner_left_join_values(map_values_t m1, map_values_t m2) {
- map_values_t::const_iterator itr;
- map_values_t ret;
+static constant_folding_c::map_values_t inner_left_join_values(constant_folding_c::map_values_t m1, constant_folding_c::map_values_t m2) {
+ constant_folding_c::map_values_t::const_iterator itr;
+ constant_folding_c::map_values_t ret;
itr = m1.begin();
for ( ; itr != m1.end(); ++itr) {
@@ -1171,7 +1168,7 @@
/* global_var_name ':' (simple_specification|subrange_specification|enumerated_specification|array_specification|prev_declared_structure_type_name|function_block_type_name */
//SYM_REF2(external_declaration_c, global_var_name, specification)
void *constant_folding_c::visit(external_declaration_c *symbol) {
- // Note that specification->const_value will have been set by handle_var_extern_global_pair, which is called from declaration_check_c
+ // Note that specification->const_value will have been set by handle_var_extern_global_pair(), which is called from declaration_check_c
symbol->global_var_name->const_value = symbol->specification->const_value;
if (fixed_init_value_) {
std::string varName = get_var_name_c::get_name(symbol->global_var_name)->value;
@@ -1182,33 +1179,70 @@
return NULL;
}
-/* Visitors related to GLOBAL variables are not really needed,
- * as they are already handled by handle_var_extern_global_pair, which is called from declaration_check_c
- *
+/* NOTE that the constant folding of GLOBAL variables is already handled by handle_var_extern_global_pair, which
+ * is called from declaration_check_c,
* This is done like this because we need to know the pairing of external<->global variables to get the cvalue
* from the global variable. Since the external<->global pairing information is available in the declaration_check_c,
* we have that class call the constant_folding_c::handle_var_extern_global_pair(), which will actually do the
* constant folding of the global and the external variable declarations!
*/
+/* NOTE: The constant propagation portion of this algorithm must still be done here!!
+ * Even though the constant folding of GLOBAL variables are already handled by handle_var_extern_global_pair(),
+ * we must still visit them here, since when doing constant propagation of a Configuration or a Resource we need the
+ * values of constant variables to be placed in the values[] map, as these same variables may be used to declare
+ * arrays of a variable size
+ * VAR_GLOBAL CONSTANT max : INT := 42; END_VAR
+ * VAR_GLOBAL array_v : ARRAY [1..max] of INT; END_VAR <---- NOTE the use of 'max' in the subrange!
+ */
/*| VAR_GLOBAL [CONSTANT|RETAIN] global_var_decl_list END_VAR */
/* option -> may be NULL ! */
// SYM_REF2(global_var_declarations_c, option, global_var_decl_list)
+/* Note that calling handle_var_decl() will result in doing constant folding of literals (of datatype initial values)
+ * that were already constant folded by the method handle_var_extern_global_pair()
+ * Nevertheless, since constant folding is idem-potent, it is simpler to just call handle_var_decl() instead
+ * of writing some code specific for this situation!
+ */
+void *constant_folding_c::visit(global_var_declarations_c *symbol) {return handle_var_decl(symbol->global_var_decl_list, is_constant(symbol->option));}
+
+
/* helper symbol for global_var_declarations */
/*| global_var_decl_list global_var_decl ';' */
// SYM_LIST(global_var_decl_list_c)
+// void *constant_folding_c::visit(global_var_decl_list_c *symbol) {} // Not needed: we inherit from iterator_c
+
/*| global_var_spec ':' [located_var_spec_init|function_block_type_name] */
/* type_specification ->may be NULL ! */
//SYM_REF2(global_var_decl_c, global_var_spec, type_specification)
+void *constant_folding_c::visit(global_var_decl_c *symbol) {
+ /* global_var_spec may be either a global_var_spec_c or a global_var_list_c.
+ * Since we already have a nice method that handles var lists (handle_var_list_decl() )
+ * if it is a global_var_spec_c we will create a temporary list so we can call that method!
+ */
+ global_var_spec_c *var_spec = dynamic_cast<global_var_spec_c *>(symbol->global_var_spec);
+ if (NULL == var_spec) {
+ // global_var_spec is a global_var_list_c
+ return handle_var_list_decl(symbol->global_var_spec, symbol->type_specification);
+ } else {
+ global_var_list_c var_list;
+ var_list.add_element(var_spec->global_var_name);
+ return handle_var_list_decl(&var_list, symbol->type_specification);
+ }
+}
+
+
/*| global_var_name location */
-//SYM_REF2(global_var_spec_c, global_var_name, location)
+//SYM_REF2(global_var_spec_c, global_var_name, location) // Not needed!
+
/* AT direct_variable */
-//SYM_REF1(location_c, direct_variable)
+//SYM_REF1(location_c, direct_variable) // Not needed!
+
/*| global_var_list ',' global_var_name */
-//SYM_LIST(global_var_list_c)
+//SYM_LIST(global_var_list_c) // Not needed!
#if 0
// TODO
+// We do not do constant folding of strings yet, so there is no need to implement this now!
/* var1_list ':' single_byte_string_spec */
SYM_REF2(single_byte_string_var_declaration_c, var1_list, single_byte_string_spec)
/* STRING ['[' integer ']'] [ASSIGN single_byte_character_string] */
@@ -1320,6 +1354,93 @@
}
+/********************************/
+/* B 1.7 Configuration elements */
+/********************************/
+
+/*
+CONFIGURATION configuration_name
+ optional_global_var_declarations
+ (resource_declaration_list | single_resource_declaration)
+ optional_access_declarations
+ optional_instance_specific_initializations
+END_CONFIGURATION
+*/
+/* enumvalue_symtable is filled in by enum_declaration_check_c, during stage3 semantic verification, with a list of all enumerated constants declared inside this POU */
+// SYM_REF5(configuration_declaration_c, configuration_name, global_var_declarations, resource_declarations, access_declarations, instance_specific_initializations,
+// enumvalue_symtable_t enumvalue_symtable; localvar_symbmap_t localvar_symbmap; localvar_symbvec_t localvar_symbvec;)
+void *constant_folding_c::visit(configuration_declaration_c *symbol) {
+ values.clear(); /* Clear global map */
+ /* Add initial value of all declared variables into Values map. */
+ function_pou_ = false;
+ return iterator_visitor_c::visit(symbol); // let the base iterator class handle the rest (basically iterate through the whole configuration and do the constant folding!
+}
+
+
+/* helper symbol for configuration_declaration */
+// SYM_LIST(resource_declaration_list_c) // Not needed: we inherit from iterator_c
+
+/*
+RESOURCE resource_name ON resource_type_name
+ optional_global_var_declarations
+ single_resource_declaration
+END_RESOURCE
+*/
+/* enumvalue_symtable is filled in by enum_declaration_check_c, during stage3 semantic verification, with a list of all enumerated constants declared inside this POU */
+// SYM_REF4(resource_declaration_c, resource_name, resource_type_name, global_var_declarations, resource_declaration,
+// enumvalue_symtable_t enumvalue_symtable; localvar_symbmap_t localvar_symbmap; localvar_symbvec_t localvar_symbvec;)
+void *constant_folding_c::visit(resource_declaration_c *symbol) {
+ values.clear(); /* Clear global map */
+ /* Add initial value of all declared variables into Values map. */
+ function_pou_ = false;
+ return iterator_visitor_c::visit(symbol); // let the base iterator class handle the rest (basically iterate through the whole configuration and do the constant folding!
+}
+
+
+
+/* task_configuration_list program_configuration_list */
+// SYM_REF2(single_resource_declaration_c, task_configuration_list, program_configuration_list)
+/* helper symbol for single_resource_declaration */
+// SYM_LIST(task_configuration_list_c)
+/* helper symbol for single_resource_declaration */
+// SYM_LIST(program_configuration_list_c)
+/* helper symbol for: (access_path, instance_specific_init) */
+// SYM_LIST(any_fb_name_list_c)
+/* [resource_name '.'] global_var_name ['.' structure_element_name] */
+// SYM_REF3(global_var_reference_c, resource_name, global_var_name, structure_element_name)
+/* prev_declared_program_name '.' symbolic_variable */
+// SYM_REF2(program_output_reference_c, program_name, symbolic_variable)
+/* TASK task_name task_initialization */
+// SYM_REF2(task_configuration_c, task_name, task_initialization)
+/* '(' [SINGLE ASSIGN data_source ','] [INTERVAL ASSIGN data_source ','] PRIORITY ASSIGN integer ')' */
+// SYM_REF3(task_initialization_c, single_data_source, interval_data_source, priority_data_source)
+/* PROGRAM [RETAIN | NON_RETAIN] program_name [WITH task_name] ':' program_type_name ['(' prog_conf_elements ')'] */
+/* NOTE: The parameter 'called_prog_declaration'is used to pass data between stage 3 and stage4 */
+// SYM_REF5(program_configuration_c, retain_option, program_name, task_name, program_type_name, prog_conf_elements,
+// symbol_c *called_prog_declaration;)
+/* prog_conf_elements ',' prog_conf_element */
+// SYM_LIST(prog_conf_elements_c)
+/* fb_name WITH task_name */
+// SYM_REF2(fb_task_c, fb_name, task_name)
+/* any_symbolic_variable ASSIGN prog_data_source */
+// SYM_REF2(prog_cnxn_assign_c, symbolic_variable, prog_data_source)
+/* any_symbolic_variable SENDTO data_sink */
+// SYM_REF2(prog_cnxn_sendto_c, symbolic_variable, data_sink)
+/* VAR_CONFIG instance_specific_init_list END_VAR */
+// SYM_REF1(instance_specific_initializations_c, instance_specific_init_list)
+/* helper symbol for instance_specific_initializations */
+// SYM_LIST(instance_specific_init_list_c)
+/* resource_name '.' program_name '.' {fb_name '.'}
+ ((variable_name [location] ':' located_var_spec_init) | (fb_name ':' fb_initialization))
+*/
+// SYM_REF6(instance_specific_init_c, resource_name, program_name, any_fb_name_list, variable_name, location, initialization)
+/* helper symbol for instance_specific_init */
+/* function_block_type_name ':=' structure_initialization */
+// SYM_REF2(fb_initialization_c, function_block_type_name, structure_initialization)
+
+
+
+
/****************************************/
/* B.2 - Language IL (Instruction List) */
/****************************************/
--- a/stage3/constant_folding.hh Thu Dec 25 08:40:15 2014 +0000
+++ b/stage3/constant_folding.hh Fri Dec 26 08:09:34 2014 +0000
@@ -61,21 +61,25 @@
/* the current IL operand being analyzed */
symbol_c *il_operand;
+
+
public:
- constant_folding_c(symbol_c *symbol = NULL);
- virtual ~constant_folding_c(void);
- int get_error_count();
- int handle_var_extern_global_pair(symbol_c *extern_var_name, symbol_c *extern_var_decl, symbol_c *global_var_name, symbol_c *global_var_decl);
+ constant_folding_c(symbol_c *symbol = NULL);
+ virtual ~constant_folding_c(void);
+ int get_error_count();
+ int handle_var_extern_global_pair(symbol_c *extern_var_name, symbol_c *extern_var_decl, symbol_c *global_var_name, symbol_c *global_var_decl);
+ typedef std::map <std::string, const_value_c> map_values_t;
private:
- void *handle_var_list_decl(symbol_c *var_list, symbol_c *type_decl);
- void *handle_var_decl (symbol_c *var_list, bool fixed_init_value);
- // Flag to indicate whether the variables in the variable declaration list will always have a fixed value when the POU is executed!
- // VAR CONSTANT ... END_VAR will always be true
- // VAR ... END_VAR will always be true for functions (who initialise local variables every time they are called), but false for FBs and PROGRAMS
- bool fixed_init_value_;
- bool function_pou_;
- bool is_constant(symbol_c *option);
- bool is_retain (symbol_c *option);
+ map_values_t values;
+ void *handle_var_list_decl(symbol_c *var_list, symbol_c *type_decl);
+ void *handle_var_decl (symbol_c *var_list, bool fixed_init_value);
+ // Flag to indicate whether the variables in the variable declaration list will always have a fixed value when the POU is executed!
+ // VAR CONSTANT ... END_VAR will always be true
+ // VAR ... END_VAR will always be true for functions (who initialise local variables every time they are called), but false for FBs and PROGRAMS
+ bool fixed_init_value_;
+ bool function_pou_;
+ bool is_constant(symbol_c *option);
+ bool is_retain (symbol_c *option);
public:
@@ -124,14 +128,16 @@
/******************************************/
/* B 1.4.3 - Declaration & Initialisation */
/******************************************/
- void *visit(var1_init_decl_c *symbol);
void *visit( input_declarations_c *symbol);
void *visit( output_declarations_c *symbol);
void *visit( input_output_declarations_c *symbol);
void *visit( var_declarations_c *symbol);
void *visit(retentive_var_declarations_c *symbol);
void *visit( external_var_declarations_c *symbol);
- void *visit(external_declaration_c *symbol);
+ void *visit( global_var_declarations_c *symbol);
+ void *visit( external_declaration_c *symbol);
+ void *visit(global_var_decl_c *symbol);
+ void *visit( var1_init_decl_c *symbol);
/**************************************/
/* B.1.5 - Program organization units */
@@ -152,7 +158,13 @@
/**********************/
/* B 1.5.3 - Programs */
/**********************/
- void *visit(program_declaration_c *symbol);
+ void *visit( program_declaration_c *symbol);
+
+ /********************************/
+ /* B 1.7 Configuration elements */
+ /********************************/
+ void *visit( configuration_declaration_c *symbol);
+ void *visit( resource_declaration_c *symbol);
/****************************************/