stage3/lvalue_check.cc
changeset 508 dc6906338042
child 509 35d391c38a30
equal deleted inserted replaced
507:30b31d8f6d0f 508:dc6906338042
       
     1 /*
       
     2  *  matiec - a compiler for the programming languages defined in IEC 61131-3
       
     3  *
       
     4  *  Copyright (C) 2009-2012  Mario de Sousa (msousa@fe.up.pt)
       
     5  *  Copyright (C) 2012       Manuele Conti  (conti.ma@alice.it)
       
     6  *
       
     7  *
       
     8  *  This program is free software: you can redistribute it and/or modify
       
     9  *  it under the terms of the GNU General Public License as published by
       
    10  *  the Free Software Foundation, either version 3 of the License, or
       
    11  *  (at your option) any later version.
       
    12  *
       
    13  *  This program is distributed in the hope that it will be useful,
       
    14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    16  *  GNU General Public License for more details.
       
    17  *
       
    18  *  You should have received a copy of the GNU General Public License
       
    19  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
       
    20  *
       
    21  *
       
    22  * This code is made available on the understanding that it will not be
       
    23  * used in safety-critical situations without a full and competent review.
       
    24  */
       
    25 
       
    26 /*
       
    27  * An IEC 61131-3 compiler.
       
    28  *
       
    29  * Based on the
       
    30  * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
       
    31  *
       
    32  */
       
    33 
       
    34 
       
    35 #include "lvalue_check.hh"
       
    36 
       
    37 #define FIRST_(symbol1, symbol2) (((symbol1)->first_order < (symbol2)->first_order)   ? (symbol1) : (symbol2))
       
    38 #define  LAST_(symbol1, symbol2) (((symbol1)->last_order  > (symbol2)->last_order)    ? (symbol1) : (symbol2))
       
    39 
       
    40 #define STAGE3_ERROR(error_level, symbol1, symbol2, ...) {                                                                  \
       
    41   if (current_display_error_level >= error_level) {                                                                         \
       
    42     fprintf(stderr, "%s:%d-%d..%d-%d: error: ",                                                                             \
       
    43             FIRST_(symbol1,symbol2)->first_file, FIRST_(symbol1,symbol2)->first_line, FIRST_(symbol1,symbol2)->first_column,\
       
    44                                                  LAST_(symbol1,symbol2) ->last_line,  LAST_(symbol1,symbol2) ->last_column);\
       
    45     fprintf(stderr, __VA_ARGS__);                                                                                           \
       
    46     fprintf(stderr, "\n");                                                                                                  \
       
    47     error_found = true;                                                                                                     \
       
    48   }                                                                                                                         \
       
    49 }
       
    50 
       
    51 
       
    52 #define STAGE3_WARNING(symbol1, symbol2, ...) {                                                                             \
       
    53     fprintf(stderr, "%s:%d-%d..%d-%d: warning: ",                                                                           \
       
    54             FIRST_(symbol1,symbol2)->first_file, FIRST_(symbol1,symbol2)->first_line, FIRST_(symbol1,symbol2)->first_column,\
       
    55                                                  LAST_(symbol1,symbol2) ->last_line,  LAST_(symbol1,symbol2) ->last_column);\
       
    56     fprintf(stderr, __VA_ARGS__);                                                                                           \
       
    57     fprintf(stderr, "\n");                                                                                                  \
       
    58     warning_found = true;                                                                                                   \
       
    59 }
       
    60 
       
    61 
       
    62 lvalue_check_c::lvalue_check_c(symbol_c *ignore) {
       
    63 	error_found = false;
       
    64 }
       
    65 
       
    66 lvalue_check_c::~lvalue_check_c(void) {
       
    67 }
       
    68 
       
    69 int lvalue_check_c::get_error_found() {
       
    70 	return error_found;
       
    71 }
       
    72 
       
    73 /* No writing to iterator variables (used in FOR loops) inside the loop itself */
       
    74 void lvalue_check_c::check_for_controlvar_assignment(symbolic_variable_c * lvalue) {
       
    75 	for (unsigned int i = 0; i < control_variables.size(); i++) {
       
    76 		symbolic_variable_c *cvar = (symbolic_variable_c *)control_variables[i];
       
    77 		if (strcasecmp(((identifier_c *)lvalue->var_name)->value, ((identifier_c *)cvar->var_name)->value) == 0) {
       
    78 			STAGE3_ERROR(0, lvalue, lvalue, "Assignment to FOR control variable are not be allowed.");
       
    79 			break;
       
    80 		}
       
    81 	}
       
    82 }
       
    83 
       
    84 /* fb_instance.var := ...  is not valid if var is output (not input ??) variable */
       
    85 void lvalue_check_c::check_output_assignment(symbolic_variable_c * lvalue) {
       
    86 	symbol_c *type_id = search_varfb_instance_type->get_basetype_id(lvalue->var_name);
       
    87 	if (NULL != type_id) {
       
    88 		function_block_declaration_c *fb_decl = function_block_type_symtable.find_value(type_id);
       
    89 		if (function_block_type_symtable.end_value() != fb_decl) {
       
    90 			search_var_instance_decl_c   search_var_instance_decl(fb_decl);
       
    91 			structured_variable_c * str_var = (structured_variable_c *)lvalue;
       
    92 			unsigned int vartype = search_var_instance_decl.get_vartype(str_var->field_selector);
       
    93 			if (vartype == search_var_instance_decl_c::output_vt)
       
    94 				STAGE3_ERROR(0, lvalue, lvalue, "Assignment to FB output field variable are not be allowed.");
       
    95 		}
       
    96 	}
       
    97 }
       
    98 
       
    99 /*  No writing to CONSTANTs */
       
   100 void lvalue_check_c::check_constant_assignment(symbolic_variable_c *lvalue) {
       
   101 	unsigned int option = search_var_instance_decl->get_option(lvalue->var_name);
       
   102 	if (option == search_var_instance_decl_c::constant_opt) {
       
   103 		STAGE3_ERROR(0, lvalue, lvalue, "Assignment to CONSTANT variables are not be allowed.");
       
   104 	}
       
   105 }
       
   106 
       
   107 /* function_name(45)  will check whether the first parameter of the function is not an output variable. */
       
   108 /* function_name(var_name)  will check whether var_name is lvalue if the first parameter of the function is an output variable. */
       
   109 void lvalue_check_c::check_function_call_parameter(function_invocation_c *f_call) {
       
   110 	function_declaration_c *f_decl;
       
   111 	identifier_c *param_name;
       
   112 	symbol_c *call_param_value;
       
   113 
       
   114 	if (NULL == f_call)
       
   115 		return;
       
   116 	/* We use called_function_declaration and for this reason LVALUE
       
   117 	 * check must be run after DATA TYPE check
       
   118 	 */
       
   119 	if (NULL == f_call->called_function_declaration)
       
   120 		ERROR;
       
   121 	f_decl = (function_declaration_c *)f_call->called_function_declaration;
       
   122 	search_constant_type_c search_constant_type;
       
   123 	function_call_param_iterator_c fcp_iterator(f_call);
       
   124 	function_param_iterator_c       fp_iterator(f_decl);
       
   125 	do {
       
   126 		param_name = fp_iterator.next();
       
   127 		if(param_name == NULL) return;
       
   128 	} while ((strcmp(param_name->value, "EN")  == 0) || (strcmp(param_name->value, "ENO") == 0));
       
   129 	while((call_param_value = fcp_iterator.next_nf()) != NULL) {
       
   130 		if (search_constant_type.is_constant_value(call_param_value)) {
       
   131 			if (function_param_iterator_c::direction_out == fp_iterator.param_direction())
       
   132 				STAGE3_ERROR(0, call_param_value, call_param_value, "Assignment Constant value to Output parameter are not be allowed.");
       
   133 		}
       
   134 		param_name = fp_iterator.next();
       
   135 	}
       
   136 }
       
   137 
       
   138 
       
   139 
       
   140 /**************************************/
       
   141 /* B 1.5 - Program organisation units */
       
   142 /**************************************/
       
   143 /***********************/
       
   144 /* B 1.5.1 - Functions */
       
   145 /***********************/
       
   146 void *lvalue_check_c::visit(function_declaration_c *symbol) {
       
   147 	search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
       
   148 	search_var_instance_decl = new search_var_instance_decl_c(symbol);
       
   149 	symbol->function_body->accept(*this);
       
   150 	delete search_varfb_instance_type;
       
   151 	delete search_var_instance_decl;
       
   152 	search_varfb_instance_type = NULL;
       
   153 	search_var_instance_decl = NULL;
       
   154 	return NULL;
       
   155 }
       
   156 
       
   157 /*****************************/
       
   158 /* B 1.5.2 - Function blocks */
       
   159 /*****************************/
       
   160 void *lvalue_check_c::visit(function_block_declaration_c *symbol) {
       
   161 	search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
       
   162 	search_var_instance_decl = new search_var_instance_decl_c(symbol);
       
   163 	symbol->fblock_body->accept(*this);
       
   164 	delete search_varfb_instance_type;
       
   165 	delete search_var_instance_decl;
       
   166 	search_varfb_instance_type = NULL;
       
   167 	search_var_instance_decl = NULL;
       
   168 	return NULL;
       
   169 }
       
   170 
       
   171 /**********************/
       
   172 /* B 1.5.3 - Programs */
       
   173 /**********************/
       
   174 void *lvalue_check_c::visit(program_declaration_c *symbol) {
       
   175 	search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
       
   176 	search_var_instance_decl = new search_var_instance_decl_c(symbol);
       
   177 	symbol->function_block_body->accept(*this);
       
   178 	delete search_varfb_instance_type;
       
   179 	delete search_var_instance_decl;
       
   180 	search_varfb_instance_type = NULL;
       
   181 	search_var_instance_decl = NULL;
       
   182 	return NULL;
       
   183 }
       
   184 
       
   185 /***************************************/
       
   186 /* B.3 - Language ST (Structured Text) */
       
   187 /***************************************/
       
   188 /***********************/
       
   189 /* B 3.1 - Expressions */
       
   190 /***********************/
       
   191 void *lvalue_check_c::visit(function_invocation_c *symbol) {
       
   192 	check_function_call_parameter(symbol);
       
   193 	return NULL;
       
   194 }
       
   195 
       
   196 /*********************************/
       
   197 /* B 3.2.1 Assignment Statements */
       
   198 /*********************************/
       
   199 void *lvalue_check_c::visit(assignment_statement_c *symbol) {
       
   200 	symbolic_variable_c *lvalue;
       
   201 
       
   202 	lvalue = (symbolic_variable_c *)symbol->l_exp;
       
   203 	check_for_controlvar_assignment(lvalue);
       
   204 	check_output_assignment(lvalue);
       
   205 	check_constant_assignment(lvalue);
       
   206 	/* We call visit r_exp to check function_call */
       
   207 	symbol->r_exp->accept(*this);
       
   208 	return NULL;
       
   209 }
       
   210 
       
   211 /********************************/
       
   212 /* B 3.2.4 Iteration Statements */
       
   213 /********************************/
       
   214 void *lvalue_check_c::visit(for_statement_c *symbol) {
       
   215 	control_variables.push_back(symbol->control_variable);
       
   216 	symbol->statement_list->accept(*this);
       
   217 	control_variables.pop_back();
       
   218 	return NULL;
       
   219 }
       
   220 
       
   221 
       
   222 
       
   223 
       
   224 
       
   225 
       
   226