# HG changeset patch # User Mario de Sousa # Date 1328125751 0 # Node ID d48f53715f77149c7dd5610c2f77836d4dc9aaee # Parent 0c2ef191b22a0478c768aae40f9d5b256d8cc70b Re-write of stage3 code (done by Manuele and I), re-write of search_varfb_instance_type_c (done by myself), and several other bug fixes. diff -r 0c2ef191b22a -r d48f53715f77 absyntax/absyntax.cc --- a/absyntax/absyntax.cc Wed Feb 01 13:01:08 2012 +0000 +++ b/absyntax/absyntax.cc Wed Feb 01 19:49:11 2012 +0000 @@ -61,6 +61,7 @@ this->last_line = last_line; this->last_column = last_column; this->last_order = last_order; + this->datatype = NULL; } diff -r 0c2ef191b22a -r d48f53715f77 absyntax/absyntax.def --- a/absyntax/absyntax.def Wed Feb 01 13:01:08 2012 +0000 +++ b/absyntax/absyntax.def Wed Feb 01 19:49:11 2012 +0000 @@ -1047,12 +1047,12 @@ /* nonformal_param_list -> may be NULL ! */ /* NOTE: The parameter 'called_function_declaration' is used to pass data between the stage 3 and stage 4. * The IEC 61131-3 standard allows for overloaded standard functions. This means that some - * function calls are not compeletely defined by the name of the function being called, + * function calls are not completely defined by the name of the function being called, * and need to be disambiguated with using the data types of the parameters being passed. - * Stage 3 does this to verify semantic correctnes. + * Stage 3 does this to verify semantic correctness. * Stage 4 also needs to do this in order to determine which function to call. * It does not make sense to determine the exact function being called twice (once in stage 3, - * and again in stage 4), so stage 3 will store this infor in the parameter called_function_declaration + * and again in stage 4), so stage 3 will store this info in the parameter called_function_declaration * for stage 4 to use it later on. */ SYM_REF3(function_invocation_c, function_name, formal_param_list, nonformal_param_list, symbol_c *called_function_declaration; int extensible_param_count;) diff -r 0c2ef191b22a -r d48f53715f77 absyntax/absyntax.hh --- a/absyntax/absyntax.hh Wed Feb 01 13:01:08 2012 +0000 +++ b/absyntax/absyntax.hh Wed Feb 01 19:49:11 2012 +0000 @@ -47,6 +47,7 @@ #include // required for NULL +#include /* Forward declaration of the visitor interface * dclared in the visitor.hh file @@ -76,6 +77,9 @@ int last_column; const char *last_file; /* filename referenced by last line/column */ long int last_order; /* relative order in which it is read by lexcial analyser */ + symbol_c * datatype; /* data type of the expression/literal/etc. Filled in stage3 by narrow_candidate_datatypes_c */ + std::vector candidate_datatypes; /* All possible data types the expression/literal/etc. may take. Filled in stage3 by fill_candidate_datatypes_c class */ + public: /* default constructor */ diff -r 0c2ef191b22a -r d48f53715f77 absyntax/visitor.cc --- a/absyntax/visitor.cc Wed Feb 01 13:01:08 2012 +0000 +++ b/absyntax/visitor.cc Wed Feb 01 19:49:11 2012 +0000 @@ -73,13 +73,13 @@ #define SYM_LIST(class_name_c) \ void *null_visitor_c::visit(class_name_c *symbol) {return NULL;} -#define SYM_TOKEN(class_name_c) \ - void *null_visitor_c::visit(class_name_c *symbol) {return NULL;} - -#define SYM_REF0(class_name_c) \ - void *null_visitor_c::visit(class_name_c *symbol) {return NULL;} - -#define SYM_REF1(class_name_c, ref1) \ +#define SYM_TOKEN(class_name_c, ...) \ + void *null_visitor_c::visit(class_name_c *symbol) {return NULL;} + +#define SYM_REF0(class_name_c, ...) \ + void *null_visitor_c::visit(class_name_c *symbol) {return NULL;} + +#define SYM_REF1(class_name_c, ref1, ...) \ void *null_visitor_c::visit(class_name_c *symbol) {return NULL;} #define SYM_REF2(class_name_c, ref1, ref2, ...) \ @@ -136,13 +136,13 @@ #define SYM_LIST(class_name_c) \ void *iterator_visitor_c::visit(class_name_c *symbol) {return visit_list(symbol);} -#define SYM_TOKEN(class_name_c) \ +#define SYM_TOKEN(class_name_c, ...) \ void *iterator_visitor_c::visit(class_name_c *symbol) {return NULL;} -#define SYM_REF0(class_name_c) \ +#define SYM_REF0(class_name_c, ...) \ void *iterator_visitor_c::visit(class_name_c *symbol) {return NULL;} -#define SYM_REF1(class_name_c, ref1) \ +#define SYM_REF1(class_name_c, ref1, ...) \ void *iterator_visitor_c::visit(class_name_c *symbol) { \ if (symbol->ref1!=NULL) symbol->ref1->accept(*this); \ return NULL; \ @@ -238,13 +238,13 @@ #define SYM_LIST(class_name_c) \ void *search_visitor_c::visit(class_name_c *symbol) {return visit_list(symbol);} -#define SYM_TOKEN(class_name_c) \ +#define SYM_TOKEN(class_name_c, ...) \ void *search_visitor_c::visit(class_name_c *symbol) {return NULL;} -#define SYM_REF0(class_name_c) \ +#define SYM_REF0(class_name_c, ...) \ void *search_visitor_c::visit(class_name_c *symbol) {return NULL;} -#define SYM_REF1(class_name_c, ref1) \ +#define SYM_REF1(class_name_c, ref1, ...) \ void *search_visitor_c::visit(class_name_c *symbol) { \ if (symbol->ref1) return symbol->ref1->accept(*this); \ return NULL; \ diff -r 0c2ef191b22a -r d48f53715f77 absyntax_utils/get_sizeof_datatype.cc --- a/absyntax_utils/get_sizeof_datatype.cc Wed Feb 01 13:01:08 2012 +0000 +++ b/absyntax_utils/get_sizeof_datatype.cc Wed Feb 01 19:49:11 2012 +0000 @@ -80,6 +80,7 @@ /* tell stdint.h we want the definition of UINT64_MAX */ #define __STDC_LIMIT_MACROS #include // get definition of uint64_t and UINT64_MAX +#include #define ERROR error_exit(__FILE__,__LINE__) @@ -158,8 +159,60 @@ /* NOTE: all integer_c and real_c tokens will always be positive (i.e. no leading '-') * due to the way the source code is parsed by iec.flex. */ + +/* + * IEC6113-3 and C++ use IEC 60559 to rappresent floating point data types + * REAL => float => single precision 32 bit + * LREAL => double => double precision 64 bit + * ????? => long double => quadruple precision 128 bit + */ void *get_sizeof_datatype_c::visit(real_c *symbol) { - return _encode_int(32); + char *endp; + long double ld_test; + double d_test; + float f_test; + + /* copy the original string, but leave out any underscores... */ + char *sval, *oval; + const char *pval; + oval = sval = (char *)malloc(strlen(symbol->value)+1); + if (NULL == sval) ERROR; + + for (pval = symbol->value, sval = oval; *pval != '\0'; pval++) { + if ('_' != *pval) {*sval = *pval; sval++;} + } + *sval = '\0'; + + sval = oval; + if ('\0' == *sval) ERROR; + + /* now do the conversion using the new string... */ + f_test = strtof(sval, &endp); + if (*endp != '\0') ERROR; + if (ERANGE != errno) { + /* No overflow/underflow! => It fits in a float! */ + free(oval); + return _encode_int(32); + } + + d_test = strtod(sval, &endp); + if (*endp != '\0') ERROR; + if (ERANGE != errno) { + /* No overflow/underflow! => It fits in a double! */ + free(oval); + return _encode_int(64); + } + + ld_test = strtold(sval, &endp); + if (*endp != '\0') ERROR; + if (ERANGE != errno) { + /* No overflow/underflow! => It fits in a long double! */ + free(oval); + return _encode_int(128); + } + + free(oval); + return _encode_int(65535); /* a very large number!!! */ } void *get_sizeof_datatype_c::visit(neg_real_c *symbol) { @@ -282,7 +335,7 @@ if (('0' != *sval) && ('1' != *sval) && ('_' != *sval)) ERROR; - if ('_' != *sval) bitsize ++; /* 1 bits per binary digit */ + if ('_' != *sval) bitsize++; /* 1 bits per binary digit */ } /* special case... if (value == 0) <=> (bitsize == 0), return bit size of 1 ! */ diff -r 0c2ef191b22a -r d48f53715f77 absyntax_utils/search_base_type.cc --- a/absyntax_utils/search_base_type.cc Wed Feb 01 13:01:08 2012 +0000 +++ b/absyntax_utils/search_base_type.cc Wed Feb 01 19:49:11 2012 +0000 @@ -1,7 +1,7 @@ /* * matiec - a compiler for the programming languages defined in IEC 61131-3 * - * Copyright (C) 2003-2011 Mario de Sousa (msousa@fe.up.pt) + * Copyright (C) 2003-2012 Mario de Sousa (msousa@fe.up.pt) * Copyright (C) 2007-2011 Laurent Bessard and Edouard Tisserant * * This program is free software: you can redistribute it and/or modify @@ -55,16 +55,29 @@ search_base_type_c::search_base_type_c(void) {current_type_name = NULL;} -void *search_base_type_c::visit(identifier_c *type_name) { - this->current_type_name = type_name; - /* look up the type declaration... */ - symbol_c *type_decl = type_symtable.find_value(type_name); - if (type_decl == type_symtable.end_value()) - /* Type declaration not found!! */ - ERROR; - - return type_decl->accept(*this); -} + + + +symbol_c *search_base_type_c::get_basetype_decl(symbol_c *symbol) { + if (NULL == symbol) + return NULL; + + return (symbol_c *)symbol->accept(*this); +} + +symbol_c *search_base_type_c::get_basetype_id (symbol_c *symbol) { + if (NULL == symbol) + return NULL; + + current_type_name = NULL; /* just to be on the safe side... */ + symbol->accept(*this); + return (symbol_c *)current_type_name; +} + + +/* Note by MJS: The following two functions definately do not belong in this class!! Maybe create a new utility class? + * I will need to clean this up when the opportunity arises! + */ bool search_base_type_c::type_is_subrange(symbol_c* type_decl) { this->is_subrange = false; @@ -78,6 +91,35 @@ return this->is_enumerated; } + +/*************************/ +/* B.1 - Common elements */ +/*************************/ + +/*******************************************/ +/* B 1.1 - Letters, digits and identifiers */ +/*******************************************/ +void *search_base_type_c::visit(identifier_c *type_name) { + symbol_c *type_decl; + + this->current_type_name = type_name; + + /* look up the type declaration... */ + type_decl = type_symtable.find_value(type_name); + if (type_decl != type_symtable.end_value()) + return type_decl->accept(*this); + + type_decl = function_block_type_symtable.find_value(type_name); + if (type_decl != function_block_type_symtable.end_value()) + return type_decl->accept(*this); + + /* Type declaration not found!! */ + ERROR; + + return NULL; +} + + /*********************/ /* B 1.2 - Constants */ /*********************/ @@ -205,8 +247,7 @@ /* helper symbol for enumerated_specification->enumerated_spec_init */ /* enumerated_value_list ',' enumerated_value */ void *search_base_type_c::visit(enumerated_value_list_c *symbol) { - if (NULL == this->current_type_name) ERROR; - return (void *)this->current_type_name; + return (void *)symbol; } /* enumerated_type_name '#' identifier */ @@ -222,14 +263,16 @@ /* array_specification [ASSIGN array_initialization} */ /* array_initialization may be NULL ! */ void *search_base_type_c::visit(array_spec_init_c *symbol) { + /* Note that the 'array_specification' may be either an identifier of a previsously defined array type, + * or an array_specification_c, so we can not stop here and simply return a array_spec_init_c, + * especially if we are looking for the base class! + */ return symbol->array_specification->accept(*this); } /* ARRAY '[' array_subrange_list ']' OF non_generic_type_name */ void *search_base_type_c::visit(array_specification_c *symbol) { - if (NULL == this->current_type_name) - this->current_type_name = symbol->non_generic_type_name; - return symbol->non_generic_type_name->accept(*this); + return symbol; } /* helper symbol for array_specification */ diff -r 0c2ef191b22a -r d48f53715f77 absyntax_utils/search_base_type.hh --- a/absyntax_utils/search_base_type.hh Wed Feb 01 13:01:08 2012 +0000 +++ b/absyntax_utils/search_base_type.hh Wed Feb 01 19:49:11 2012 +0000 @@ -1,7 +1,7 @@ /* * matiec - a compiler for the programming languages defined in IEC 61131-3 * - * Copyright (C) 2003-2011 Mario de Sousa (msousa@fe.up.pt) + * Copyright (C) 2003-2012 Mario de Sousa (msousa@fe.up.pt) * Copyright (C) 2007-2011 Laurent Bessard and Edouard Tisserant * * This program is free software: you can redistribute it and/or modify @@ -60,18 +60,27 @@ search_base_type_c(void); public: - void *visit(identifier_c *type_name); + symbol_c *get_basetype_decl(symbol_c *symbol); + symbol_c *get_basetype_id (symbol_c *symbol); bool type_is_subrange(symbol_c* type_decl); bool type_is_enumerated(symbol_c* type_decl); public: - /*********************/ - /* B 1.2 - Constants */ - /*********************/ - - /******************************/ - /* B 1.2.1 - Numeric Literals */ - /******************************/ + /*************************/ + /* B.1 - Common elements */ + /*************************/ + /*******************************************/ + /* B 1.1 - Letters, digits and identifiers */ + /*******************************************/ + void *visit(identifier_c *type_name); + + + /*********************/ + /* B 1.2 - Constants */ + /*********************/ + /******************************/ + /* B 1.2.1 - Numeric Literals */ + /******************************/ /* Numeric literals without any explicit type cast have unknown data type, * so we continue considering them as their own basic data types until * they can be resolved (for example, when using '30+x' where 'x' is a LINT variable, the diff -r 0c2ef191b22a -r d48f53715f77 absyntax_utils/search_constant_type.cc --- a/absyntax_utils/search_constant_type.cc Wed Feb 01 13:01:08 2012 +0000 +++ b/absyntax_utils/search_constant_type.cc Wed Feb 01 19:49:11 2012 +0000 @@ -155,16 +155,26 @@ time_type_name_c search_constant_type_c::time_type_name; int_type_name_c search_constant_type_c::int_type_name; -// safebool_type_name_c search_constant_type_c::safebool_type_name; - /* The following is required because the expression (TOD_var - TOD_var) will result in a data type - * (in this case, TIME) that is neither of the expression elements... - */ safetime_type_name_c search_constant_type_c::safetime_type_name; safetod_type_name_c search_constant_type_c::safetod_type_name; safedt_type_name_c search_constant_type_c::safedt_type_name; +safedate_type_name_c search_constant_type_c::safedate_type_name; +safereal_type_name_c search_constant_type_c::safereal_type_name; +safesint_type_name_c search_constant_type_c::safesint_type_name; +safelint_type_name_c search_constant_type_c::safelint_type_name; +safedint_type_name_c search_constant_type_c::safedint_type_name; +safedword_type_name_c search_constant_type_c::safedword_type_name; +safeudint_type_name_c search_constant_type_c::safeudint_type_name; +safeword_type_name_c search_constant_type_c::safeword_type_name; +safewstring_type_name_c search_constant_type_c::safewstring_type_name; +safestring_type_name_c search_constant_type_c::safestring_type_name; +safelword_type_name_c search_constant_type_c::safelword_type_name; +safeuint_type_name_c search_constant_type_c::safeuint_type_name; +safelreal_type_name_c search_constant_type_c::safelreal_type_name; +safebyte_type_name_c search_constant_type_c::safebyte_type_name; +safeusint_type_name_c search_constant_type_c::safeusint_type_name; +safeulint_type_name_c search_constant_type_c::safeulint_type_name; +safebool_type_name_c search_constant_type_c::safebool_type_name; +safeint_type_name_c search_constant_type_c::safeint_type_name; - -/* temporarily here until we remove the st_code_gen.c and il_code_gen.c files... */ -/* It should then move to search_expression_type_c */ -integer_c search_constant_type_c::integer("1"); diff -r 0c2ef191b22a -r d48f53715f77 absyntax_utils/search_constant_type.hh --- a/absyntax_utils/search_constant_type.hh Wed Feb 01 13:01:08 2012 +0000 +++ b/absyntax_utils/search_constant_type.hh Wed Feb 01 19:49:11 2012 +0000 @@ -95,8 +95,24 @@ static safetime_type_name_c safetime_type_name; static safetod_type_name_c safetod_type_name; static safedt_type_name_c safedt_type_name; - - + static safedate_type_name_c safedate_type_name; + static safereal_type_name_c safereal_type_name; + static safesint_type_name_c safesint_type_name; + static safelint_type_name_c safelint_type_name; + static safedint_type_name_c safedint_type_name; + static safedword_type_name_c safedword_type_name; + static safeudint_type_name_c safeudint_type_name; + static safeword_type_name_c safeword_type_name; + static safewstring_type_name_c safewstring_type_name; + static safestring_type_name_c safestring_type_name; + static safelword_type_name_c safelword_type_name; + static safeuint_type_name_c safeuint_type_name; + static safelreal_type_name_c safelreal_type_name; + static safebyte_type_name_c safebyte_type_name; + static safeusint_type_name_c safeusint_type_name; + static safeulint_type_name_c safeulint_type_name; + static safebool_type_name_c safebool_type_name; + static safeint_type_name_c safeint_type_name; public: symbol_c *get_type(symbol_c *constant); @@ -163,5 +179,4 @@ }; // search_constant_type_c - #endif /* ifndef _SEARCH_CONSTANT_TYPE_HH */ diff -r 0c2ef191b22a -r d48f53715f77 absyntax_utils/search_var_instance_decl.cc --- a/absyntax_utils/search_var_instance_decl.cc Wed Feb 01 13:01:08 2012 +0000 +++ b/absyntax_utils/search_var_instance_decl.cc Wed Feb 01 19:49:11 2012 +0000 @@ -77,10 +77,14 @@ return (symbol_c *)search_scope->accept(*this); } -unsigned int search_var_instance_decl_c::get_vartype(void) { +unsigned int search_var_instance_decl_c::get_vartype(symbol_c *variable_instance_name) { + this->current_vartype = none_vt; + this->search_name = variable_instance_name; + search_scope->accept(*this); return current_vartype; } + /***************************/ /* B 0 - Programming Model */ /***************************/ diff -r 0c2ef191b22a -r d48f53715f77 absyntax_utils/search_var_instance_decl.hh --- a/absyntax_utils/search_var_instance_decl.hh Wed Feb 01 13:01:08 2012 +0000 +++ b/absyntax_utils/search_var_instance_decl.hh Wed Feb 01 19:49:11 2012 +0000 @@ -77,7 +77,8 @@ public: search_var_instance_decl_c(symbol_c *search_scope); symbol_c *get_decl(symbol_c *variable_instance_name); - unsigned int get_vartype(void); + + unsigned int get_vartype(symbol_c *variable_instance_name); public: diff -r 0c2ef191b22a -r d48f53715f77 absyntax_utils/search_varfb_instance_type.cc --- a/absyntax_utils/search_varfb_instance_type.cc Wed Feb 01 13:01:08 2012 +0000 +++ b/absyntax_utils/search_varfb_instance_type.cc Wed Feb 01 19:49:11 2012 +0000 @@ -1,7 +1,7 @@ /* * matiec - a compiler for the programming languages defined in IEC 61131-3 * - * Copyright (C) 2003-2011 Mario de Sousa (msousa@fe.up.pt) + * Copyright (C) 2003-2012 Mario de Sousa (msousa@fe.up.pt) * Copyright (C) 2007-2011 Laurent Bessard and Edouard Tisserant * * This program is free software: you can redistribute it and/or modify @@ -75,225 +75,134 @@ * * Member functions: * ================ + * get_basetype_id() ---> returns 2A (implemented, although currently it is not needed! ) * get_basetype_decl() ---> returns 2B * get_type_id() ---> returns 1A * - * Since we haven't yet needed them, we don't yet implement - * get_basetype_id() ----> would return 2A - * get_type_decl() ----> would return 1B + * Since we haven't yet needed it, we don't yet implement + * get_type_decl() ---> returns 1B */ -/* - * TODO: this code has a memory leak... - * We call 'new' in several locations, but bever get to 'delete' the object instances... - */ + #include "absyntax_utils.hh" +void search_varfb_instance_type_c::init(void) { + this->current_type_id = NULL; + this->current_basetype_id = NULL; + this->current_basetype_decl = NULL; + this->current_field_selector = NULL; + this->is_complex = false; +} + + search_varfb_instance_type_c::search_varfb_instance_type_c(symbol_c *search_scope): search_var_instance_decl(search_scope) { - this->decompose_var_instance_name = NULL; - this->current_structelement_name = NULL; - this->current_typeid = NULL; - this->current_basetypeid = NULL; -} - -symbol_c *search_varfb_instance_type_c::get_type_decl(symbol_c *variable_name) { - this->current_structelement_name = NULL; - this->current_typeid = NULL; - this->current_basetypeid = NULL; - this->decompose_var_instance_name = new decompose_var_instance_name_c(variable_name); - if (NULL == decompose_var_instance_name) ERROR; - - /* find the part of the variable name that will appear in the - * variable declaration, for e.g., in window.point.x, this would be - * window! - */ - symbol_c *var_name_part = decompose_var_instance_name->next_part(); - if (NULL == var_name_part) ERROR; - - /* Now we try to find the variable instance declaration, to determine its type... */ - symbol_c *var_decl = search_var_instance_decl.get_decl(var_name_part); - if (NULL == var_decl) ERROR; - - /* if it is a struct or function block, we must search the type - * of the struct or function block member. - * This is done by this class visiting the var_decl. - * This class, while visiting, will recursively call - * decompose_var_instance_name->get_next() when and if required... - */ - symbol_c *res = (symbol_c *)var_decl->accept(*this); - /* NOTE: A Null result is not really an internal compiler error, but rather an error in - * the IEC 61131-3 source code being compiled. This means we cannot just abort the compiler with ERROR. - * // if (NULL == res) ERROR; - */ - if (NULL == res) return NULL; - - /* make sure that we have decomposed all structure elements of the variable name */ - symbol_c *var_name = decompose_var_instance_name->next_part(); - /* NOTE: A non-NULL result is not really an internal compiler error, but rather an error in - * the IEC 61131-3 source code being compiled. - * (for example, 'int_var.struct_elem' in the source code, when 'int_var' is a simple integer, - * and not a structure, will result in this result being non-NULL!) - * This means we cannot just abort the compiler with ERROR. - * // if (NULL != var_name) ERROR; - */ - if (NULL != var_name) return NULL; - - return res; + this->init(); +} + + +/* We expect to be passed a symbolic_variable_c */ +symbol_c *search_varfb_instance_type_c::get_type_id(symbol_c *variable_name) { + this->init(); + variable_name->accept(*this); + return current_type_id; +} + + +symbol_c *search_varfb_instance_type_c::get_basetype_id(symbol_c *variable_name) { + this->init(); + variable_name->accept(*this); + return current_basetype_id; } symbol_c *search_varfb_instance_type_c::get_basetype_decl(symbol_c *variable_name) { - symbol_c *res = get_type_decl(variable_name); - if (NULL == res) return NULL; - return (symbol_c *)base_type(res); + this->init(); + variable_name->accept(*this); + return current_basetype_decl; } + + + unsigned int search_varfb_instance_type_c::get_vartype(symbol_c *variable_name) { - this->current_structelement_name = NULL; - this->current_typeid = NULL; - this->current_basetypeid = NULL; - this->is_complex = false; - this->decompose_var_instance_name = new decompose_var_instance_name_c(variable_name); - if (NULL == decompose_var_instance_name) ERROR; - - /* find the part of the variable name that will appear in the - * variable declaration, for e.g., in window.point.x, this would be - * window! - */ - symbol_c *var_name_part = decompose_var_instance_name->next_part(); - if (NULL == var_name_part) ERROR; - - /* Now we try to find the variable instance declaration, to determine its type... */ - symbol_c *var_decl = search_var_instance_decl.get_decl(var_name_part); - if (NULL == var_decl) { - /* variable instance declaration not found! */ - return 0; - } - - /* if it is a struct or function block, we must search the type - * of the struct or function block member. - * This is done by this class visiting the var_decl. - * This class, while visiting, will recursively call - * decompose_var_instance_name->get_next() when and if required... - */ - var_decl->accept(*this); - unsigned int res = search_var_instance_decl.get_vartype(); - - /* make sure that we have decomposed all structure elements of the variable name */ - symbol_c *var_name = decompose_var_instance_name->next_part(); - if (NULL != var_name) ERROR; - - return res; -} - -symbol_c *search_varfb_instance_type_c::get_type_id(symbol_c *variable_name) { - this->current_typeid = NULL; - symbol_c *vartype = this->get_type_decl(variable_name); - if (this->current_typeid != NULL) - return this->current_typeid; - else - return vartype; -} + this->init(); + return search_var_instance_decl.get_vartype(variable_name); +} + + bool search_varfb_instance_type_c::type_is_complex(void) { return this->is_complex; } -/* a helper function... */ -void *search_varfb_instance_type_c::visit_list(list_c *list) { - if (NULL == current_structelement_name) ERROR; - - for(int i = 0; i < list->n; i++) { - void *res = list->elements[i]->accept(*this); - if (res != NULL) - return res; - } - /* not found! */ - return NULL; -} - -/* a helper function... */ -void *search_varfb_instance_type_c::base_type(symbol_c *symbol) { - search_base_type_c search_base_type; - return symbol->accept(search_base_type); -} - -/* We override the base class' visitor to identifier_c. - * This is so because the base class does not consider a function block - * to be a type, unlike this class that allows a variable instance - * of a function block type... - */ -void *search_varfb_instance_type_c::visit(identifier_c *type_name) { - /* we only store the new type id if none had been found yet. - * Since we will recursively carry on looking at the base type - * to determine the base type declaration and id, we must only set this variable - * the first time. - * e.g. TYPE myint1_t : int := 1; - * myint2_t : int1_t := 2; - * myint3_t : int2_t := 3; - * END_TYPE; - * VAR - * myint1 : myint1_t; - * myint2 : myint2_t; - * myint3 : myint3_t; - * END_VAR - * - * If we ask for typeid of myint3, it must return myint3_t - * If we ask for basetypeid of myint3, it must return int - * - * When determining the data type of myint3, we will recursively go all the way - * down to int, but we must still only store myint3_t as the base type id. - */ - if (NULL == this->current_typeid) - this->current_typeid = type_name; - this->current_basetypeid = type_name; - - /* look up the type declaration... */ - symbol_c *fb_decl = function_block_type_symtable.find_value(type_name); - if (fb_decl != function_block_type_symtable.end_value()) - /* Type declaration found!! */ - return fb_decl->accept(*this); - - /* No. It is not a function block, so we let - * the base class take care of it... - */ - return search_base_type_c::visit(type_name); -} + + + + + + + + /********************************/ /* B 1.3.3 - Derived data types */ /********************************/ - /* identifier ':' array_spec_init */ +/* NOTE: I don't think this will ever get called, since in the visit method for array_variable_c + * we use the basetype_decl for recursively calling this class, and the base type should never be a + * array_type_declaration_c, but for now, let's leave it in... + */ void *search_varfb_instance_type_c::visit(array_type_declaration_c *symbol) { - return symbol->array_spec_init->accept(*this); + ERROR; + return NULL; } /* array_specification [ASSIGN array_initialization] */ /* array_initialization may be NULL ! */ +/* NOTE: I don't think this will ever get called, since in the visit method for array_variable_c + * we use the basetype_decl for recursively calling this class, and the base type should never be a + * array_spec_init_c, but for now, let's leave it in... + */ void *search_varfb_instance_type_c::visit(array_spec_init_c *symbol) { - return symbol->array_specification->accept(*this); + /* Note that the 'array_specification' may be either an identifier of a previsously defined array type, + * or an array_specification_c, so we can not stop here and simply return a array_spec_init_c, + * especially if we are looking for the base class! + */ + ERROR; + return NULL; } /* ARRAY '[' array_subrange_list ']' OF non_generic_type_name */ +/* NOTE: This method will be reached after being called from the + * search_varfb_instance_type_c::visit(array_variable_c *symbol) + * method, so we must return the data type of the data stored in the array, + * and not the data type of the array itself! + */ void *search_varfb_instance_type_c::visit(array_specification_c *symbol) { - this->is_complex = true; - this->current_typeid = symbol; - return symbol->non_generic_type_name->accept(*this); -} + /* found the type of the element we were looking for! */ + current_type_id = symbol->non_generic_type_name; + current_basetype_decl = search_base_type.get_basetype_decl(current_type_id); + current_basetype_id = search_base_type.get_basetype_id (current_type_id); + + return NULL; +} + /* structure_type_name ':' structure_specification */ /* NOTE: this is only used inside a TYPE ... END_TYPE declaration. * It is never used directly when declaring a new variable! */ +/* NOTE: I don't think this will ever get called, since in the visit method for structured_variable_c + * we use the basetype_decl for recursively calling this class, and the base type should never be a + * structure_type_declaration_c, but for now, let's leave it in... + */ void *search_varfb_instance_type_c::visit(structure_type_declaration_c *symbol) { - this->is_complex = true; - - if (NULL == current_structelement_name) ERROR; - return symbol->structure_specification->accept(*this); + if (NULL == current_field_selector) ERROR; + symbol->structure_specification->accept(*this); + return NULL; /* NOTE: structure_specification will point to either a * initialized_structure_c * OR A @@ -304,51 +213,42 @@ /* structure_type_name ASSIGN structure_initialization */ /* structure_initialization may be NULL ! */ // SYM_REF2(initialized_structure_c, structure_type_name, structure_initialization) -/* NOTE: only the initialized structure is ever used when declaring a new variable instance */ +/* NOTE: only the initialized structure is never used when declaring a new variable instance */ +/* NOTE: I don't think this will ever get called, since in the visit method for structured_variable_c + * we use the basetype_decl for recursively calling this class, and the base type should never be a + * initialized_structure_c, but for now, let's leave it in... + */ void *search_varfb_instance_type_c::visit(initialized_structure_c *symbol) { - this->is_complex = true; - if (NULL != current_structelement_name) ERROR; - - /* make sure that we have decomposed all structure elements of the variable name */ - symbol_c *var_name = decompose_var_instance_name->next_part(); - if (NULL == var_name) { - /* this is it... ! - * No need to look any further... - * Note also that, unlike for the struct types, a function block may - * not be defined based on another (i.e. no inheritance is allowed), - * so this function block is already the most base type. - * We simply return it. - */ - return (void *)symbol; - } - - /* reset current_type_id because of new structure element part */ - this->current_typeid = NULL; - - /* look for the var_name in the structure declaration */ - current_structelement_name = var_name; - - /* recursively find out the data type of current_structelement_name... */ - return symbol->structure_type_name->accept(*this); + if (NULL != current_field_selector) ERROR; + + /* recursively find out the data type of current_field_selector... */ + symbol->structure_type_name->accept(*this); + return NULL; } /* helper symbol for structure_declaration */ /* structure_declaration: STRUCT structure_element_declaration_list END_STRUCT */ /* structure_element_declaration_list structure_element_declaration ';' */ void *search_varfb_instance_type_c::visit(structure_element_declaration_list_c *symbol) { - if (NULL == current_structelement_name) ERROR; + if (NULL == current_field_selector) ERROR; + /* now search the structure declaration */ - return visit_list(symbol); + for(int i = 0; i < symbol->n; i++) { + symbol->elements[i]->accept(*this); + } + + return NULL; } /* structure_element_name ':' spec_init */ void *search_varfb_instance_type_c::visit(structure_element_declaration_c *symbol) { - if (NULL == current_structelement_name) ERROR; - - if (compare_identifiers(symbol->structure_element_name, current_structelement_name) == 0) { - current_structelement_name = NULL; + if (NULL == current_field_selector) ERROR; + + if (compare_identifiers(symbol->structure_element_name, current_field_selector) == 0) { /* found the type of the element we were looking for! */ - return symbol->spec_init->accept(*this); + current_type_id = symbol->spec_init; + current_basetype_decl = search_base_type.get_basetype_decl(current_type_id); + current_basetype_id = search_base_type.get_basetype_id (current_type_id); } /* Did not find the type of the element we were looking for! */ @@ -364,6 +264,79 @@ void *search_varfb_instance_type_c::visit(structure_element_initialization_c *symbol) {ERROR; return NULL;} /* should never get called... */ +/*********************/ +/* B 1.4 - Variables */ +/*********************/ +// SYM_REF1(symbolic_variable_c, var_name) +void *search_varfb_instance_type_c::visit(symbolic_variable_c *symbol) { + /* Note: although the method is called get_decl(), it is getting the declaration of the variable, which for us is the type_id of that variable! */ + current_type_id = search_var_instance_decl.get_decl (symbol->var_name); + current_basetype_decl = search_base_type.get_basetype_decl(current_type_id); + current_basetype_id = search_base_type.get_basetype_id (current_type_id); + + if (NULL == current_type_id) ERROR; /* why should this be an error? what if the variable has not been declared? */ + + return NULL; +} + +/********************************************/ +/* B.1.4.1 Directly Represented Variables */ +/********************************************/ +// SYM_TOKEN(direct_variable_c) +/* We do not yet handle this. Will we ever need to handle it, as the data type of the direct variable is + * directly obtainable from the syntax of the direct variable itself? + */ + +/*************************************/ +/* B 1.4.2 - Multi-element variables */ +/*************************************/ +/* subscripted_variable '[' subscript_list ']' */ +// SYM_REF2(array_variable_c, subscripted_variable, subscript_list) +/* NOTE: when passed a array_variable_c, which represents some IEC61131-3 code similar to X[42] + * we must return the data type of the value _stored_ in the array. + * If you want to get the data type of the array itself (i.e. just the X variable, without the [42]) + * then this class must be called with the identifier_c 'X'. + */ +void *search_varfb_instance_type_c::visit(array_variable_c *symbol) { + this->is_complex = true; + + /* determine the data type of the subscripted_variable... + * This should be an array_specification_c + * ARRAY [xx..yy] OF Stored_Data_Type + */ + symbol->subscripted_variable->accept(*this); + + /* Now we determine the 'Stored_Data_Type', i.e. the data type of the variable stored in the array. */ + if (NULL != current_basetype_decl) { + current_basetype_decl->accept(*this); + } + + return NULL; +} + + +/* record_variable '.' field_selector */ +/* WARNING: input and/or output variables of function blocks + * may be accessed as fields of a structured variable! + * Code handling a structured_variable_c must take + * this into account! + */ +// SYM_REF2(structured_variable_c, record_variable, field_selector) +void *search_varfb_instance_type_c::visit(structured_variable_c *symbol) { + this->is_complex = true; + symbol->record_variable->accept(*this); + + /* Now we search for the data type of the field... But only if we were able to determine the data type of the variable */ + if (NULL != current_basetype_decl) { + current_field_selector = symbol->field_selector; + current_basetype_decl->accept(*this); + current_field_selector = NULL; + } + + return NULL; +} + + /**************************************/ /* B.1.5 - Program organization units */ @@ -371,46 +344,18 @@ /*****************************/ /* B 1.5.2 - Function Blocks */ /*****************************/ + /* FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations function_block_body END_FUNCTION_BLOCK */ // SYM_REF4(function_block_declaration_c, fblock_name, var_declarations, fblock_body, unused) void *search_varfb_instance_type_c::visit(function_block_declaration_c *symbol) { - /* make sure that we have decomposed all structure elements of the variable name */ - symbol_c *var_name = decompose_var_instance_name->next_part(); - if (NULL == var_name) { - /* this is it... ! - * No need to look any further... - * Note also that, unlike for the struct types, a function block may - * not be defined based on another (i.e. no inheritance is allowed), - * so this function block is already the most base type. - * We simply return it. - */ - return (void *)symbol; - } - - /* reset current_type_id because of new structure element part */ - this->current_typeid = NULL; - - /* now search the function block declaration for the variable... */ - search_var_instance_decl_c search_decl(symbol); - symbol_c *var_decl = search_decl.get_decl(var_name); - if (NULL == var_decl) { - /* variable instance declaration not found! */ - return NULL; - } -#if 0 - /* We have found the declaration. - * Should we look any further? - */ - var_name = decompose_var_instance_name->next_part(); - if (NULL == var_name) { - /* this is it... ! */ - return base_type(var_decl); - } - - current_structelement_name = var_name; - /* recursively find out the data type of var_name... */ - return symbol->var_declarations->accept(*this); -#endif - /* carry on recursively, in case the variable has more elements to be decomposed... */ - return var_decl->accept(*this); -} + if (NULL == current_field_selector) ERROR; + + /* now search the function block declaration for the variable... */ + /* If not found, these pointers will all be set to NULL!! */ + search_var_instance_decl_c search_decl(symbol); + current_type_id = search_decl.get_decl(current_field_selector); + current_basetype_decl = search_base_type.get_basetype_decl(current_type_id); + current_basetype_id = search_base_type.get_basetype_id (current_type_id); + + return NULL; +} diff -r 0c2ef191b22a -r d48f53715f77 absyntax_utils/search_varfb_instance_type.hh --- a/absyntax_utils/search_varfb_instance_type.hh Wed Feb 01 13:01:08 2012 +0000 +++ b/absyntax_utils/search_varfb_instance_type.hh Wed Feb 01 19:49:11 2012 +0000 @@ -1,7 +1,7 @@ /* * matiec - a compiler for the programming languages defined in IEC 61131-3 * - * Copyright (C) 2003-2011 Mario de Sousa (msousa@fe.up.pt) + * Copyright (C) 2003-2012 Mario de Sousa (msousa@fe.up.pt) * Copyright (C) 2007-2011 Laurent Bessard and Edouard Tisserant * * This program is free software: you can redistribute it and/or modify @@ -77,28 +77,37 @@ * * Member functions: * ================ + * get_basetype_id() ---> returns 2A (implemented, although currently it is not needed! ) * get_basetype_decl() ---> returns 2B * get_type_id() ---> returns 1A * - * Since we haven't yet needed them, we don't yet implement - * get_basetype_id() ----> would return 2A - * get_type_decl() ----> would return 1B + * Since we haven't yet needed it, we don't yet implement + * get_type_decl() ---> returns 1B */ -class search_varfb_instance_type_c: public search_base_type_c { +class search_varfb_instance_type_c : null_visitor_c { private: search_var_instance_decl_c search_var_instance_decl; - decompose_var_instance_name_c *decompose_var_instance_name; - symbol_c *current_structelement_name; - symbol_c *current_typeid; - symbol_c *current_basetypeid; + search_base_type_c search_base_type; + +// symbol_c *current_type_decl; + symbol_c *current_type_id; + symbol_c *current_basetype_decl; + symbol_c *current_basetype_id; + + symbol_c *current_field_selector; + bool is_complex; + + /* sets all the above variables to NULL, or false */ + void init(void); public: search_varfb_instance_type_c(symbol_c *search_scope); symbol_c *get_basetype_decl(symbol_c *variable_name); - symbol_c *get_type_decl(symbol_c *variable_name); + symbol_c *get_basetype_id (symbol_c *variable_name); +// symbol_c *get_type_decl(symbol_c *variable_name); symbol_c *get_type_id(symbol_c *variable_name); /* NOTE: this function should be remvoed/deleted. @@ -130,12 +139,11 @@ * to be a type, unlike this class that allows a variable instance * of a function block type... */ - void *visit(identifier_c *type_name); +// void *visit(identifier_c *type_name); /********************************/ /* B 1.3.3 - Derived data types */ /********************************/ - /* identifier ':' array_spec_init */ void *visit(array_type_declaration_c *symbol); @@ -170,7 +178,20 @@ void *visit(structure_element_initialization_c *symbol); /* should never get called... */ - + /*********************/ + /* B 1.4 - Variables */ + /*********************/ + void *visit(symbolic_variable_c *symbol); + + /********************************************/ + /* B.1.4.1 Directly Represented Variables */ + /********************************************/ + /*************************************/ + /* B 1.4.2 - Multi-element variables */ + /*************************************/ + void *visit(array_variable_c *symbol); + void *visit(structured_variable_c *symbol); + /**************************************/ /* B.1.5 - Program organization units */ /**************************************/ diff -r 0c2ef191b22a -r d48f53715f77 stage1_2/iec_bison.yy --- a/stage1_2/iec_bison.yy Wed Feb 01 13:01:08 2012 +0000 +++ b/stage1_2/iec_bison.yy Wed Feb 01 19:49:11 2012 +0000 @@ -2791,7 +2791,7 @@ | signed_integer DOTDOT error {$$ = NULL; if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no value defined for upper bound in subrange definition.");} - else {print_err_msg(locf(@3), locl(@3), "invalid value for upper bound in subrange definition."); yyclearin;} + else {print_err_msg(locf(@3), locl(@3), "invalid value for lower bound in subrange definition."); yyclearin;} yyerrok; } /* ERROR_CHECK_END */ diff -r 0c2ef191b22a -r d48f53715f77 stage3/Makefile.am --- a/stage3/Makefile.am Wed Feb 01 13:01:08 2012 +0000 +++ b/stage3/Makefile.am Wed Feb 01 19:49:11 2012 +0000 @@ -4,5 +4,8 @@ libstage3_a_SOURCES = \ stage3.cc \ - visit_expression_type.cc + fill_candidate_datatypes.cc \ + narrow_candidate_datatypes.cc \ + print_datatypes_error.cc \ + datatype_functions.cc diff -r 0c2ef191b22a -r d48f53715f77 stage3/Makefile.in --- a/stage3/Makefile.in Wed Feb 01 13:01:08 2012 +0000 +++ b/stage3/Makefile.in Wed Feb 01 19:49:11 2012 +0000 @@ -33,7 +33,7 @@ PRE_UNINSTALL = : POST_UNINSTALL = : DIST_COMMON = $(srcdir)/../common.mk $(srcdir)/Makefile.am \ - $(srcdir)/Makefile.in + $(srcdir)/Makefile.in TODO subdir = stage3 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac @@ -71,7 +71,9 @@ libstage3_a_AR = $(AR) $(ARFLAGS) libstage3_a_LIBADD = am_libstage3_a_OBJECTS = stage3.$(OBJEXT) \ - visit_expression_type.$(OBJEXT) + fill_candidate_datatypes.$(OBJEXT) \ + narrow_candidate_datatypes.$(OBJEXT) \ + print_datatypes_error.$(OBJEXT) datatype_functions.$(OBJEXT) libstage3_a_OBJECTS = $(am_libstage3_a_OBJECTS) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/config depcomp = $(SHELL) $(top_srcdir)/config/depcomp @@ -188,7 +190,10 @@ lib_LIBRARIES = libstage3.a libstage3_a_SOURCES = \ stage3.cc \ - visit_expression_type.cc + fill_candidate_datatypes.cc \ + narrow_candidate_datatypes.cc \ + print_datatypes_error.cc \ + datatype_functions.cc all: all-am @@ -267,8 +272,11 @@ distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/datatype_functions.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fill_candidate_datatypes.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/narrow_candidate_datatypes.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/print_datatypes_error.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stage3.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/visit_expression_type.Po@am__quote@ .cc.o: @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< diff -r 0c2ef191b22a -r d48f53715f77 stage3/datatype_functions.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stage3/datatype_functions.cc Wed Feb 01 19:49:11 2012 +0000 @@ -0,0 +1,620 @@ +/* + * matiec - a compiler for the programming languages defined in IEC 61131-3 + * + * Copyright (C) 2009-2012 Mario de Sousa (msousa@fe.up.pt) + * Copyright (C) 2012 Manuele Conti (conti.ma@alice.it) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * This code is made available on the understanding that it will not be + * used in safety-critical situations without a full and competent review. + */ + +#include "datatype_functions.hh" +#include "../absyntax_utils/absyntax_utils.hh" + +/* + * 2.5.1.5.6 Functions of time data types + * Table 30 - page 64 + */ + +const struct widen_entry widen_ADD_table[] = { + { &search_constant_type_c::time_type_name, &search_constant_type_c::time_type_name, &search_constant_type_c::time_type_name }, + { &search_constant_type_c::tod_type_name, &search_constant_type_c::tod_type_name, &search_constant_type_c::tod_type_name }, + { &search_constant_type_c::dt_type_name, &search_constant_type_c::dt_type_name, &search_constant_type_c::dt_type_name }, + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safetime_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::safetod_type_name, &search_constant_type_c::safetod_type_name, &search_constant_type_c::safetod_type_name }, + { &search_constant_type_c::safedt_type_name, &search_constant_type_c::safedt_type_name, &search_constant_type_c::safedt_type_name }, + { &search_constant_type_c::tod_type_name, &search_constant_type_c::time_type_name, &search_constant_type_c::tod_type_name }, + { &search_constant_type_c::safetod_type_name, &search_constant_type_c::time_type_name, &search_constant_type_c::tod_type_name }, + { &search_constant_type_c::tod_type_name, &search_constant_type_c::safetime_type_name, &search_constant_type_c::tod_type_name }, + { &search_constant_type_c::safetod_type_name, &search_constant_type_c::safetime_type_name, &search_constant_type_c::safetod_type_name }, + { &search_constant_type_c::dt_type_name, &search_constant_type_c::time_type_name, &search_constant_type_c::dt_type_name }, + { &search_constant_type_c::safedt_type_name, &search_constant_type_c::time_type_name, &search_constant_type_c::dt_type_name }, + { &search_constant_type_c::dt_type_name, &search_constant_type_c::safetime_type_name, &search_constant_type_c::dt_type_name }, + { &search_constant_type_c::safedt_type_name, &search_constant_type_c::safetime_type_name, &search_constant_type_c::safedt_type_name }, + { NULL, NULL, NULL }, +}; + + +const struct widen_entry widen_SUB_table[] = { + { &search_constant_type_c::time_type_name, &search_constant_type_c::time_type_name, &search_constant_type_c::time_type_name }, + { &search_constant_type_c::tod_type_name, &search_constant_type_c::tod_type_name, &search_constant_type_c::tod_type_name }, + { &search_constant_type_c::dt_type_name, &search_constant_type_c::dt_type_name, &search_constant_type_c::dt_type_name }, + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safetime_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::safetod_type_name, &search_constant_type_c::safetod_type_name, &search_constant_type_c::safetod_type_name }, + { &search_constant_type_c::safedt_type_name, &search_constant_type_c::safedt_type_name, &search_constant_type_c::safedt_type_name }, + + { &search_constant_type_c::tod_type_name, &search_constant_type_c::time_type_name, &search_constant_type_c::tod_type_name }, + { &search_constant_type_c::safetod_type_name, &search_constant_type_c::time_type_name, &search_constant_type_c::tod_type_name }, + { &search_constant_type_c::tod_type_name, &search_constant_type_c::safetime_type_name, &search_constant_type_c::tod_type_name }, + { &search_constant_type_c::safetod_type_name, &search_constant_type_c::safetime_type_name, &search_constant_type_c::safetod_type_name }, + { &search_constant_type_c::dt_type_name, &search_constant_type_c::time_type_name, &search_constant_type_c::dt_type_name }, + { &search_constant_type_c::safedt_type_name, &search_constant_type_c::time_type_name, &search_constant_type_c::dt_type_name }, + { &search_constant_type_c::dt_type_name, &search_constant_type_c::safetime_type_name, &search_constant_type_c::dt_type_name }, + { &search_constant_type_c::safedt_type_name, &search_constant_type_c::safetime_type_name, &search_constant_type_c::safedt_type_name }, + { &search_constant_type_c::tod_type_name, &search_constant_type_c::tod_type_name, &search_constant_type_c::time_type_name }, + { &search_constant_type_c::safetod_type_name, &search_constant_type_c::tod_type_name, &search_constant_type_c::time_type_name }, + { &search_constant_type_c::tod_type_name, &search_constant_type_c::safetod_type_name, &search_constant_type_c::time_type_name }, + { &search_constant_type_c::safetod_type_name, &search_constant_type_c::safetod_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::date_type_name, &search_constant_type_c::date_type_name, &search_constant_type_c::time_type_name }, + { &search_constant_type_c::safedate_type_name, &search_constant_type_c::date_type_name, &search_constant_type_c::time_type_name }, + { &search_constant_type_c::date_type_name, &search_constant_type_c::safedate_type_name, &search_constant_type_c::time_type_name }, + { &search_constant_type_c::safedate_type_name, &search_constant_type_c::safedate_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::dt_type_name, &search_constant_type_c::dt_type_name, &search_constant_type_c::time_type_name }, + { &search_constant_type_c::safedt_type_name, &search_constant_type_c::dt_type_name, &search_constant_type_c::time_type_name }, + { &search_constant_type_c::dt_type_name, &search_constant_type_c::safedt_type_name, &search_constant_type_c::time_type_name }, + { &search_constant_type_c::safedt_type_name, &search_constant_type_c::safedt_type_name, &search_constant_type_c::safetime_type_name }, + { NULL, NULL, NULL }, +}; + +const struct widen_entry widen_MUL_table[] = { + { &search_constant_type_c::time_type_name, &search_constant_type_c::lreal_type_name, &search_constant_type_c::time_type_name }, + { &search_constant_type_c::time_type_name, &search_constant_type_c::real_type_name, &search_constant_type_c::time_type_name }, + { &search_constant_type_c::time_type_name, &search_constant_type_c::dint_type_name, &search_constant_type_c::time_type_name }, + { &search_constant_type_c::time_type_name, &search_constant_type_c::int_type_name, &search_constant_type_c::time_type_name }, + { &search_constant_type_c::time_type_name, &search_constant_type_c::sint_type_name, &search_constant_type_c::time_type_name }, + { &search_constant_type_c::time_type_name, &search_constant_type_c::ulint_type_name, &search_constant_type_c::time_type_name }, + { &search_constant_type_c::time_type_name, &search_constant_type_c::udint_type_name, &search_constant_type_c::time_type_name }, + { &search_constant_type_c::time_type_name, &search_constant_type_c::uint_type_name, &search_constant_type_c::time_type_name }, + { &search_constant_type_c::time_type_name, &search_constant_type_c::usint_type_name, &search_constant_type_c::time_type_name }, + + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::lreal_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::real_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::dint_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::int_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::sint_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::ulint_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::udint_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::uint_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::usint_type_name, &search_constant_type_c::safetime_type_name }, + + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safelreal_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safereal_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safedint_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safeint_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safesint_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safeulint_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safeudint_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safeuint_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safeusint_type_name, &search_constant_type_c::safetime_type_name }, + + { NULL, NULL, NULL }, +}; + +const struct widen_entry widen_DIV_table[] = { + { &search_constant_type_c::time_type_name, &search_constant_type_c::lreal_type_name, &search_constant_type_c::time_type_name }, + { &search_constant_type_c::time_type_name, &search_constant_type_c::real_type_name, &search_constant_type_c::time_type_name }, + { &search_constant_type_c::time_type_name, &search_constant_type_c::dint_type_name, &search_constant_type_c::time_type_name }, + { &search_constant_type_c::time_type_name, &search_constant_type_c::int_type_name, &search_constant_type_c::time_type_name }, + { &search_constant_type_c::time_type_name, &search_constant_type_c::sint_type_name, &search_constant_type_c::time_type_name }, + { &search_constant_type_c::time_type_name, &search_constant_type_c::ulint_type_name, &search_constant_type_c::time_type_name }, + { &search_constant_type_c::time_type_name, &search_constant_type_c::udint_type_name, &search_constant_type_c::time_type_name }, + { &search_constant_type_c::time_type_name, &search_constant_type_c::uint_type_name, &search_constant_type_c::time_type_name }, + { &search_constant_type_c::time_type_name, &search_constant_type_c::usint_type_name, &search_constant_type_c::time_type_name }, + + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::lreal_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::real_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::dint_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::int_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::sint_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::ulint_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::udint_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::uint_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::usint_type_name, &search_constant_type_c::safetime_type_name }, + + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safelreal_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safereal_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safedint_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safeint_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safesint_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safeulint_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safeudint_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safeuint_type_name, &search_constant_type_c::safetime_type_name }, + { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safeusint_type_name, &search_constant_type_c::safetime_type_name }, + + { NULL, NULL, NULL }, +}; + +/* NOTE on data type handling and literals... + * ========================================== + * + * Literals that are explicitly type cast + * e.g.: BYTE#42 + * INT#65 + * TIME#45h23m + * etc... + * are NOT considered literals in the following code. + * Since they are type cast, and their data type is fixed and well known, + * they are treated as a variable of that data type (except when determining lvalues) + * In other words, when calling search_constant_type_c on these constants, it returns + * a xxxxx_type_name_c, and not one of the xxxx_literal_c ! + * + * When the following code handles a literal, it is really a literal of unknown data type. + * e.g. 42, may be considered an int, a byte, a word, etc... + * + * NOTE: type_symbol == NULL is valid! + * This will occur, for example, when and undefined/undeclared symbolic_variable is used in the program. + * This will not be of any type, so we always return false. + */ + +/* A helper function... */ +bool is_ANY_ELEMENTARY_type(symbol_c *type_symbol) { + if (type_symbol == NULL) {return false;} + return is_ANY_MAGNITUDE_type(type_symbol) + || is_ANY_BIT_type (type_symbol) + || is_ANY_STRING_type (type_symbol) + || is_ANY_DATE_type (type_symbol); +} + +/* A helper function... */ +bool is_ANY_SAFEELEMENTARY_type(symbol_c *type_symbol) { + if (type_symbol == NULL) {return false;} + return is_ANY_SAFEMAGNITUDE_type(type_symbol) + || is_ANY_SAFEBIT_type (type_symbol) + || is_ANY_SAFESTRING_type (type_symbol) + || is_ANY_SAFEDATE_type (type_symbol); +} + +/* A helper function... */ +bool is_ANY_ELEMENTARY_compatible(symbol_c *type_symbol) { + if (type_symbol == NULL) {return false;} + /* NOTE: doing + * return is_ANY_SAFEELEMENTARY_type() || is_ANY_ELEMENTARY_type() + * is incorrect, as the literals would never be considered compatible... + */ + return is_ANY_MAGNITUDE_compatible(type_symbol) + || is_ANY_BIT_compatible (type_symbol) + || is_ANY_STRING_compatible (type_symbol) + || is_ANY_DATE_compatible (type_symbol); +} + + +/* A helper function... */ +bool is_ANY_MAGNITUDE_type(symbol_c *type_symbol) { + if (type_symbol == NULL) {return false;} + if (typeid(*type_symbol) == typeid(time_type_name_c)) {return true;} + return is_ANY_NUM_type(type_symbol); +} + +/* A helper function... */ +bool is_ANY_SAFEMAGNITUDE_type(symbol_c *type_symbol) { + if (type_symbol == NULL) {return false;} + if (typeid(*type_symbol) == typeid(safetime_type_name_c)) {return true;} + return is_ANY_SAFENUM_type(type_symbol); +} + +/* A helper function... */ +bool is_ANY_MAGNITUDE_compatible(symbol_c *type_symbol) { + if (type_symbol == NULL) {return false;} + if (is_ANY_MAGNITUDE_type (type_symbol)) {return true;} + if (is_ANY_SAFEMAGNITUDE_type(type_symbol)) {return true;} + + return is_ANY_NUM_compatible(type_symbol); +} + +/* A helper function... */ +bool is_ANY_NUM_type(symbol_c *type_symbol) { + if (type_symbol == NULL) {return false;} + if (is_ANY_REAL_type(type_symbol)) {return true;} + if (is_ANY_INT_type(type_symbol)) {return true;} + return false; +} + +/* A helper function... */ +bool is_ANY_SAFENUM_type(symbol_c *type_symbol) { + if (type_symbol == NULL) {return false;} + return is_ANY_SAFEREAL_type(type_symbol) + || is_ANY_SAFEINT_type (type_symbol); +} + +/* A helper function... */ +bool is_ANY_NUM_compatible(symbol_c *type_symbol) { + if (type_symbol == NULL) {return false;} + if (is_ANY_REAL_compatible(type_symbol)) {return true;} + if (is_ANY_INT_compatible(type_symbol)) {return true;} + return false; +} + +/* A helper function... */ +bool is_ANY_DATE_type(symbol_c *type_symbol) { + if (type_symbol == NULL) {return false;} + if (typeid(*type_symbol) == typeid(date_type_name_c)) {return true;} + if (typeid(*type_symbol) == typeid(tod_type_name_c)) {return true;} + if (typeid(*type_symbol) == typeid(dt_type_name_c)) {return true;} + return false; +} + +/* A helper function... */ +bool is_ANY_SAFEDATE_type(symbol_c *type_symbol) { + if (type_symbol == NULL) {return false;} + if (typeid(*type_symbol) == typeid(safedate_type_name_c)) {return true;} + if (typeid(*type_symbol) == typeid(safetod_type_name_c)) {return true;} + if (typeid(*type_symbol) == typeid(safedt_type_name_c)) {return true;} + return false; +} + +/* A helper function... */ +bool is_ANY_DATE_compatible(symbol_c *type_symbol) { + if (type_symbol == NULL) {return false;} + if (is_ANY_DATE_type (type_symbol)) {return true;} + if (is_ANY_SAFEDATE_type(type_symbol)) {return true;} + return false; +} + +/* A helper function... */ +bool is_ANY_STRING_type(symbol_c *type_symbol) { + if (type_symbol == NULL) {return false;} + if (typeid(*type_symbol) == typeid(string_type_name_c)) {return true;} + if (typeid(*type_symbol) == typeid(wstring_type_name_c)) {return true;} +// TODO literal_string ??? + return false; +} + +/* A helper function... */ +bool is_ANY_SAFESTRING_type(symbol_c *type_symbol) { + if (type_symbol == NULL) {return false;} + if (typeid(*type_symbol) == typeid(safestring_type_name_c)) {return true;} + if (typeid(*type_symbol) == typeid(safewstring_type_name_c)) {return true;} + return false; +} + +/* A helper function... */ +bool is_ANY_STRING_compatible(symbol_c *type_symbol) { + if (type_symbol == NULL) {return false;} + if (is_ANY_STRING_type (type_symbol)) {return true;} + if (is_ANY_SAFESTRING_type(type_symbol)) {return true;} + return false; +} + +/* A helper function... */ +bool is_ANY_INT_type(symbol_c *type_symbol) { + if (type_symbol == NULL) {return false;} + if (typeid(*type_symbol) == typeid(sint_type_name_c)) {return true;} + if (typeid(*type_symbol) == typeid(int_type_name_c)) {return true;} + if (typeid(*type_symbol) == typeid(dint_type_name_c)) {return true;} + if (typeid(*type_symbol) == typeid(lint_type_name_c)) {return true;} + if (typeid(*type_symbol) == typeid(usint_type_name_c)) {return true;} + if (typeid(*type_symbol) == typeid(uint_type_name_c)) {return true;} + if (typeid(*type_symbol) == typeid(udint_type_name_c)) {return true;} + if (typeid(*type_symbol) == typeid(ulint_type_name_c)) {return true;} + return false; +} + +/* A helper function... */ +bool is_ANY_SAFEINT_type(symbol_c *type_symbol) { + if (type_symbol == NULL) {return false;} + if (typeid(*type_symbol) == typeid(safesint_type_name_c)) {return true;} + if (typeid(*type_symbol) == typeid(safeint_type_name_c)) {return true;} + if (typeid(*type_symbol) == typeid(safedint_type_name_c)) {return true;} + if (typeid(*type_symbol) == typeid(safelint_type_name_c)) {return true;} + if (typeid(*type_symbol) == typeid(safeusint_type_name_c)) {return true;} + if (typeid(*type_symbol) == typeid(safeuint_type_name_c)) {return true;} + if (typeid(*type_symbol) == typeid(safeudint_type_name_c)) {return true;} + if (typeid(*type_symbol) == typeid(safeulint_type_name_c)) {return true;} + return false; +} + +/* A helper function... */ +bool is_ANY_INT_compatible(symbol_c *type_symbol) { + if (type_symbol == NULL) {return false;} + if (is_ANY_INT_type (type_symbol)) {return true;} + if (is_ANY_SAFEINT_type(type_symbol)) {return true;} + if (is_literal_integer_type(type_symbol)) {return true;} + return false; +} + +/* A helper function... */ +bool is_ANY_REAL_type(symbol_c *type_symbol) { + if (type_symbol == NULL) {return false;} + if (typeid(*type_symbol) == typeid(real_type_name_c)) {return true;} + if (typeid(*type_symbol) == typeid(lreal_type_name_c)) {return true;} + return false; +} + +/* A helper function... */ +bool is_ANY_SAFEREAL_type(symbol_c *type_symbol) { + if (type_symbol == NULL) {return false;} + if (typeid(*type_symbol) == typeid(safereal_type_name_c)) {return true;} + if (typeid(*type_symbol) == typeid(safelreal_type_name_c)) {return true;} + return false; +} + +/* A helper function... */ +bool is_ANY_REAL_compatible(symbol_c *type_symbol) { + if (type_symbol == NULL) {return false;} + if (is_ANY_REAL_type (type_symbol)) {return true;} + if (is_ANY_SAFEREAL_type(type_symbol)) {return true;} + if (is_literal_real_type(type_symbol)) {return true;} + return false; +} + +/* A helper function... */ +bool is_ANY_BIT_type(symbol_c *type_symbol) { + if (type_symbol == NULL) {return false;} + if (typeid(*type_symbol) == typeid(bool_type_name_c)) {return true;} + if (typeid(*type_symbol) == typeid(byte_type_name_c)) {return true;} + if (typeid(*type_symbol) == typeid(word_type_name_c)) {return true;} + if (typeid(*type_symbol) == typeid(dword_type_name_c)) {return true;} + if (typeid(*type_symbol) == typeid(lword_type_name_c)) {return true;} + return false; +} + +/* A helper function... */ +bool is_ANY_SAFEBIT_type(symbol_c *type_symbol) { + if (type_symbol == NULL) {return false;} + if (typeid(*type_symbol) == typeid(safebool_type_name_c)) {return true;} + if (typeid(*type_symbol) == typeid(safebyte_type_name_c)) {return true;} + if (typeid(*type_symbol) == typeid(safeword_type_name_c)) {return true;} + if (typeid(*type_symbol) == typeid(safedword_type_name_c)) {return true;} + if (typeid(*type_symbol) == typeid(safelword_type_name_c)) {return true;} + return false; +} + +/* A helper function... */ +bool is_ANY_BIT_compatible(symbol_c *type_symbol) { + if (type_symbol == NULL) {return false;} + if (is_ANY_BIT_type (type_symbol)) {return true;} + if (is_ANY_SAFEBIT_type(type_symbol)) {return true;} + if (is_nonneg_literal_integer_type(type_symbol)) {return true;} + if (is_literal_bool_type(type_symbol)) {return true;} + return false; +} + +/* A helper function... */ +bool is_BOOL_type(symbol_c *type_symbol) { + if (type_symbol == NULL) {return false;} + if (typeid(*type_symbol) == typeid(bool_type_name_c)) {return true;} + return false; +} + +/* A helper function... */ +bool is_SAFEBOOL_type(symbol_c *type_symbol){ + if (type_symbol == NULL) {return false;} + if (typeid(*type_symbol) == typeid(safebool_type_name_c)) {return true;} + return false; +} + +/* A helper function... */ +bool is_ANY_BOOL_compatible(symbol_c *type_symbol) { + if (type_symbol == NULL) {return false;} + if (is_BOOL_type (type_symbol)) {return true;} + if (is_SAFEBOOL_type(type_symbol)) {return true;} + if (is_literal_bool_type(type_symbol)) {return true;} + return false; +} + +/* A helper function... */ +bool is_literal_integer_type(symbol_c *type_symbol) { + if (type_symbol == NULL) {return false;} + if (typeid(*type_symbol) == typeid(neg_integer_c)) {return true;} + return is_nonneg_literal_integer_type(type_symbol); +} + + +/* A helper function... */ +bool is_nonneg_literal_integer_type(symbol_c *type_symbol) { + if (type_symbol == NULL) {return false;} + if (typeid(*type_symbol) == typeid(integer_c)) {return true;} + if (typeid(*type_symbol) == typeid(binary_integer_c)) {return true;} + if (typeid(*type_symbol) == typeid(octal_integer_c)) {return true;} + if (typeid(*type_symbol) == typeid(hex_integer_c)) {return true;} + return false; +} + + +/* A helper function... */ +bool is_literal_real_type(symbol_c *type_symbol) { + if (type_symbol == NULL) {return false;} + if (typeid(*type_symbol) == typeid(real_c)) {return true;} + if (typeid(*type_symbol) == typeid(neg_real_c)) {return true;} + return false; +} + + +/* A helper function... */ +bool is_literal_bool_type(symbol_c *type_symbol) { + bool_type_name_c bool_t; + + if (type_symbol == NULL) {return false;} + if (typeid(*type_symbol) == typeid(boolean_true_c)) {return true;} + if (typeid(*type_symbol) == typeid(boolean_false_c)) {return true;} + if (is_nonneg_literal_integer_type(type_symbol)) + if (sizeoftype(&bool_t) >= sizeoftype(type_symbol)) {return true;} + return false; +} + +/* Determine the common data type between two data types. + * If no common data type found, return NULL. + * + * If data types are identical, return the first (actually any would do...). + * If any of the data types is a literal, we confirm that + * the literal uses less bits than the fixed size data type. + * e.g. BYTE and 1024 returns NULL + * BYTE and 255 returns BYTE + * + * If two literals, then return the literal that requires more bits... + */ + +symbol_c *common_type(symbol_c *first_type, symbol_c *second_type) { + if (first_type == NULL && second_type == NULL) {return NULL;} + if (first_type == NULL) {return second_type;} + if (second_type == NULL) {return first_type;} + + if (is_literal_integer_type(first_type) && is_literal_integer_type(second_type)) + {return ((sizeoftype(first_type) > sizeoftype(second_type))? first_type:second_type);} + + if (is_literal_real_type(first_type) && is_literal_real_type(second_type)) + {return ((sizeoftype(first_type) > sizeoftype(second_type))? first_type:second_type);} + + if (is_literal_bool_type(first_type) && is_literal_bool_type(second_type)) + {return first_type;} + + /* The following check can only be made after the is_literal_XXXX checks */ + /* When two literals of the same type, with identical typeid's are checked, + * we must return the one that occupies more bits... This is done above. + */ + if (typeid(*first_type) == typeid(*second_type)) {return first_type;} + + /* NOTE Although a BOOL is also an ANY_BIT, we must check it explicitly since some + * literal bool values are not literal integers... + */ + if (is_BOOL_type(first_type) && is_literal_bool_type(second_type)) {return first_type;} + if (is_BOOL_type(second_type) && is_literal_bool_type(first_type)) {return second_type;} + + if (is_SAFEBOOL_type(first_type) && is_literal_bool_type(second_type)) {return first_type;} + if (is_SAFEBOOL_type(second_type) && is_literal_bool_type(first_type)) {return second_type;} + + if (is_SAFEBOOL_type(first_type) && is_BOOL_type(second_type)) {return second_type;} + if (is_SAFEBOOL_type(second_type) && is_BOOL_type(first_type)) {return first_type;} + + if (is_ANY_BIT_type(first_type) && is_nonneg_literal_integer_type(second_type)) + {return ((sizeoftype(first_type) >= sizeoftype(second_type))? first_type :NULL);} + if (is_ANY_BIT_type(second_type) && is_nonneg_literal_integer_type(first_type)) + {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);} + + if (is_ANY_SAFEBIT_type(first_type) && is_nonneg_literal_integer_type(second_type)) + {return ((sizeoftype(first_type) >= sizeoftype(second_type))? first_type :NULL);} + if (is_ANY_SAFEBIT_type(second_type) && is_nonneg_literal_integer_type(first_type)) + {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);} + + if (is_ANY_SAFEBIT_type(first_type) && is_ANY_BIT_type(second_type)) + {return ((sizeoftype(first_type) == sizeoftype(second_type))? second_type:NULL);} + if (is_ANY_SAFEBIT_type(second_type) && is_ANY_BIT_type(first_type)) + {return ((sizeoftype(first_type) == sizeoftype(second_type))? first_type :NULL);} + + if (is_ANY_INT_type(first_type) && is_literal_integer_type(second_type)) + {return ((sizeoftype(first_type) >= sizeoftype(second_type))? first_type :NULL);} + if (is_ANY_INT_type(second_type) && is_literal_integer_type(first_type)) + {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);} + + if (is_ANY_SAFEINT_type(first_type) && is_literal_integer_type(second_type)) + {return ((sizeoftype(first_type) >= sizeoftype(second_type))? first_type :NULL);} + if (is_ANY_SAFEINT_type(second_type) && is_literal_integer_type(first_type)) + {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);} + + if (is_ANY_SAFEINT_type(first_type) && is_ANY_INT_type(second_type)) + {return ((sizeoftype(first_type) == sizeoftype(second_type))? second_type:NULL);} + if (is_ANY_SAFEINT_type(second_type) && is_ANY_INT_type(first_type)) + {return ((sizeoftype(first_type) == sizeoftype(second_type))? first_type :NULL);} + + if (is_ANY_REAL_type(first_type) && is_literal_real_type(second_type)) + {return ((sizeoftype(first_type) >= sizeoftype(second_type))? first_type :NULL);} + if (is_ANY_REAL_type(second_type) && is_literal_real_type(first_type)) + {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);} + + if (is_ANY_SAFEREAL_type(first_type) && is_literal_real_type(second_type)) + {return ((sizeoftype(first_type) >= sizeoftype(second_type))? first_type :NULL);} + if (is_ANY_SAFEREAL_type(second_type) && is_literal_real_type(first_type)) + {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);} + + if (is_ANY_SAFEREAL_type(first_type) && is_ANY_REAL_type(second_type)) + {return ((sizeoftype(first_type) == sizeoftype(second_type))? second_type:NULL);} + if (is_ANY_SAFEREAL_type(second_type) && is_ANY_REAL_type(first_type)) + {return ((sizeoftype(first_type) == sizeoftype(second_type))? first_type :NULL);} + + /* the Time and Date types... */ + if (is_type(first_type, safetime_type_name_c) && is_type(second_type, time_type_name_c)) {return second_type;} + if (is_type(second_type, safetime_type_name_c) && is_type( first_type, time_type_name_c)) {return first_type;} + + if (is_type(first_type, safedate_type_name_c) && is_type(second_type, date_type_name_c)) {return second_type;} + if (is_type(second_type, safedate_type_name_c) && is_type( first_type, date_type_name_c)) {return first_type;} + + if (is_type(first_type, safedt_type_name_c) && is_type(second_type, dt_type_name_c)) {return second_type;} + if (is_type(second_type, safedt_type_name_c) && is_type( first_type, dt_type_name_c)) {return first_type;} + + if (is_type(first_type, safetod_type_name_c) && is_type(second_type, tod_type_name_c)) {return second_type;} + if (is_type(second_type, safetod_type_name_c) && is_type( first_type, tod_type_name_c)) {return first_type;} + + /* no common type */ + return NULL; +} + +/* Return TRUE if the second (value) data type may be assigned to a variable of the first (variable) data type + * such as: + * var_type value_type + * BOOL BYTE#7 -> returns false + * INT INT#7 -> returns true + * INT 7 -> returns true + * REAL 7.89 -> returns true + * REAL 7 -> returns true + * INT 7.89 -> returns false + * SAFEBOOL BOOL#1 -> returns false !!! + * etc... + * + * NOTE: It is assumed that the var_type is the data type of an lvalue + */ +bool is_valid_assignment(symbol_c *var_type, symbol_c *value_type) { + if (var_type == NULL) {/* STAGE3_ERROR(value_type, value_type, "Var_type == NULL"); */ return false;} + if (value_type == NULL) {/* STAGE3_ERROR(var_type, var_type, "Value_type == NULL"); */ return false;} + + symbol_c *common_type_symbol = common_type(var_type, value_type); + if (NULL == common_type_symbol) + return false; + return (typeid(*var_type) == typeid(*common_type_symbol)); +} + + +/* Return TRUE if there is a common data type, otherwise return FALSE + * i.e., return TRUE if both data types may be used simultaneously in an expression + * such as: + * BOOL#0 AND BYTE#7 -> returns false + * 0 AND BYTE#7 -> returns true + * INT#10 AND INT#7 -> returns true + * INT#10 AND 7 -> returns true + * REAL#34.3 AND 7.89 -> returns true + * REAL#34.3 AND 7 -> returns true + * INT#10 AND 7.89 -> returns false + * SAFEBOOL#0 AND BOOL#1 -> returns true !!! + * etc... + */ +bool is_compatible_type(symbol_c *first_type, symbol_c *second_type) { + if (first_type == NULL || second_type == NULL) {return false;} + return (NULL != common_type(first_type, second_type)); +} + +bool is_type_equal(symbol_c *first_type, symbol_c *second_type) +{ + if (first_type == NULL || second_type == NULL) { + return false; + } + if (is_ANY_ELEMENTARY_type(first_type)) { + if (typeid(*first_type) == typeid(*second_type)) + return true; + } else /* ANY_DERIVED */ + return (first_type == second_type); + + return false; +} diff -r 0c2ef191b22a -r d48f53715f77 stage3/datatype_functions.hh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stage3/datatype_functions.hh Wed Feb 01 19:49:11 2012 +0000 @@ -0,0 +1,111 @@ +/* + * matiec - a compiler for the programming languages defined in IEC 61131-3 + * + * Copyright (C) 2009-2012 Mario de Sousa (msousa@fe.up.pt) + * Copyright (C) 2012 Manuele Conti (conti.ma@alice.it) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * This code is made available on the understanding that it will not be + * used in safety-critical situations without a full and competent review. + */ + +#ifndef _HELPER_FUNCTIONS_HH_ +#define _HELPER_FUNCTIONS_HH_ + +#include "../absyntax/visitor.hh" +#include + +#define is_type(type_name_symbol, type_name_class) ((type_name_symbol == NULL) ? false : (typeid(*type_name_symbol) == typeid(type_name_class))) +#define sizeoftype(symbol) get_sizeof_datatype_c::getsize(symbol) + +/* Widening Primitive Conversion */ +struct widen_entry { + symbol_c *left; + symbol_c *right; + symbol_c *result; +}; +/* + * 2.5.1.5.6 Functions of time data types + * Table 30 - page 64 + */ +extern const struct widen_entry widen_ADD_table[]; +extern const struct widen_entry widen_SUB_table[]; +extern const struct widen_entry widen_MUL_table[]; +extern const struct widen_entry widen_DIV_table[]; + +/* A helper function... */ +bool is_ANY_ELEMENTARY_type (symbol_c *type_symbol); +bool is_ANY_SAFEELEMENTARY_type (symbol_c *type_symbol); +bool is_ANY_ELEMENTARY_compatible (symbol_c *type_symbol); + +bool is_ANY_MAGNITUDE_type (symbol_c *type_symbol); +bool is_ANY_SAFEMAGNITUDE_type (symbol_c *type_symbol); +bool is_ANY_MAGNITUDE_compatible (symbol_c *type_symbol); + +bool is_ANY_DATE_type (symbol_c *type_symbol); +bool is_ANY_SAFEDATE_type (symbol_c *type_symbol); +bool is_ANY_DATE_compatible (symbol_c *type_symbol); + +bool is_ANY_STRING_type (symbol_c *type_symbol); +bool is_ANY_SAFESTRING_type (symbol_c *type_symbol); +bool is_ANY_STRING_compatible (symbol_c *type_symbol); + +bool is_ANY_INT_type (symbol_c *type_symbol); +bool is_ANY_SAFEINT_type (symbol_c *type_symbol); +bool is_ANY_INT_compatible (symbol_c *type_symbol); + +bool is_ANY_REAL_type (symbol_c *type_symbol); +bool is_ANY_SAFEREAL_type (symbol_c *type_symbol); +bool is_ANY_REAL_compatible (symbol_c *type_symbol); + +bool is_ANY_NUM_type (symbol_c *type_symbol); +bool is_ANY_SAFENUM_type (symbol_c *type_symbol); +bool is_ANY_NUM_compatible (symbol_c *type_symbol); + +bool is_ANY_BIT_type (symbol_c *type_symbol); +bool is_ANY_SAFEBIT_type (symbol_c *type_symbol); +bool is_ANY_BIT_compatible (symbol_c *type_symbol); + +bool is_BOOL_type (symbol_c *type_symbol); +bool is_SAFEBOOL_type (symbol_c *type_symbol); +bool is_ANY_BOOL_compatible (symbol_c *type_symbol); + +bool is_nonneg_literal_integer_type (symbol_c *type_symbol); +bool is_literal_integer_type (symbol_c *type_symbol); +bool is_literal_real_type (symbol_c *type_symbol); +bool is_literal_bool_type (symbol_c *type_symbol); + +/* Determine the common data type between two data types. + * If no common data type found, return NULL. + * + * If data types are identical, return the first (any would do...). + * If any of the data types is a literal, we confirm that + * the literal uses less bits than the fixed size data type. + * e.g. BYTE and 1024 returns NULL + * BYTE and 255 returns BYTE + * + * If two literals, then return the literal that requires more bits... + */ +symbol_c *common_type(symbol_c *first_type, symbol_c *second_type); +bool is_valid_assignment(symbol_c *var_type, symbol_c *value_type); +bool is_compatible_type(symbol_c *first_type, symbol_c *second_type); +bool is_type_equal(symbol_c *first_type, symbol_c *second_type); + +typedef bool (*helper_function_t) (symbol_c *type_symbol); /* a pointer to a function! */ + + + +#endif /* _HELPER_FUNCTIONS_HH_ */ diff -r 0c2ef191b22a -r d48f53715f77 stage3/fill_candidate_datatypes.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stage3/fill_candidate_datatypes.cc Wed Feb 01 19:49:11 2012 +0000 @@ -0,0 +1,1830 @@ +/* + * matiec - a compiler for the programming languages defined in IEC 61131-3 + * + * Copyright (C) 2009-2012 Mario de Sousa (msousa@fe.up.pt) + * Copyright (C) 2012 Manuele Conti (manuele.conti@sirius-es.it) + * Copyright (C) 2012 Matteo Facchinetti (matteo.facchinetti@sirius-es.it) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * This code is made available on the understanding that it will not be + * used in safety-critical situations without a full and competent review. + */ + +/* + * An IEC 61131-3 compiler. + * + * Based on the + * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10) + * + */ + + +/* + * Fill candidate list of data types for all symbols + */ + +#include "fill_candidate_datatypes.hh" +#include "datatype_functions.hh" +#include +#include +#include +#include +#include + +/* set to 1 to see debug info during execution */ +static int debug = 0; + +fill_candidate_datatypes_c::fill_candidate_datatypes_c(symbol_c *ignore) { + +} + +fill_candidate_datatypes_c::~fill_candidate_datatypes_c(void) { +} + +symbol_c *fill_candidate_datatypes_c::widening_conversion(symbol_c *left_type, symbol_c *right_type, const struct widen_entry widen_table[]) { + int k; + /* find a widening table entry compatible */ + for (k = 0; NULL != widen_table[k].left; k++) + if ((typeid(*left_type) == typeid(*widen_table[k].left)) && (typeid(*right_type) == typeid(*widen_table[k].right))) + return widen_table[k].result; + return NULL; +} + +void fill_candidate_datatypes_c::match_nonformal_call(symbol_c *f_call, symbol_c *f_decl, int *error_count) { + symbol_c *call_param_value, *param_type; + identifier_c *param_name; + function_param_iterator_c fp_iterator(f_decl); + function_call_param_iterator_c fcp_iterator(f_call); + int extensible_parameter_highest_index = -1; + unsigned int i; + + /* reset error counter */ + if (error_count != NULL) *error_count = 0; + /* Iterating through the non-formal parameters of the function call */ + while((call_param_value = fcp_iterator.next_nf()) != NULL) { + /* Obtaining the type of the value being passed in the function call */ + std::vector &call_param_types = call_param_value->candidate_datatypes; + /* Iterate to the next parameter of the function being called. + * Get the name of that parameter, and ignore if EN or ENO. + */ + do { + param_name = fp_iterator.next(); + /* If there is no other parameter declared, then we are passing too many parameters... */ + if(param_name == NULL) { + (*error_count)++; + return; + } + } while ((strcmp(param_name->value, "EN") == 0) || (strcmp(param_name->value, "ENO") == 0)); + + /* Get the parameter type */ + param_type = base_type(fp_iterator.param_type()); + for(i = 0; i < call_param_types.size(); i++) { + /* If the declared parameter and the parameter from the function call do not have the same type */ + if(is_type_equal(param_type, call_param_types[i])) { + break; + } + } + if (i >= call_param_types.size()) (*error_count)++; + } +} + +void fill_candidate_datatypes_c::match_formal_call(symbol_c *f_call, symbol_c *f_decl, int *error_count) { + symbol_c *call_param_value, *call_param_name, *param_type; + symbol_c *verify_duplicate_param; + identifier_c *param_name; + function_param_iterator_c fp_iterator(f_decl); + function_call_param_iterator_c fcp_iterator(f_call); + int extensible_parameter_highest_index = -1; + identifier_c *extensible_parameter_name; + unsigned int i; + + /* reset error counter */ + if (error_count != NULL) *error_count = 0; + + /* Iterating through the formal parameters of the function call */ + while((call_param_name = fcp_iterator.next_f()) != NULL) { + + /* Obtaining the value being passed in the function call */ + call_param_value = fcp_iterator.get_current_value(); + /* the following should never occur. If it does, then we have a bug in our code... */ + if (NULL == call_param_value) ERROR; + + /* Checking if there are duplicated parameter values */ + verify_duplicate_param = fcp_iterator.search_f(call_param_name); + if(verify_duplicate_param != call_param_value) + (*error_count)++; + + /* Obtaining the type of the value being passed in the function call */ + std::vector &call_param_types = call_param_value->candidate_datatypes; + + + /* Find the corresponding parameter in function declaration */ + param_name = fp_iterator.search(call_param_name); + if(param_name == NULL) { + (*error_count)++; + } else { + /* Get the parameter type */ + param_type = base_type(fp_iterator.param_type()); + for (i = 0; i < call_param_types.size(); i++) { + /* If the declared parameter and the parameter from the function call have the same type */ + if(is_type_equal(param_type, call_param_types[i])) + break; + } + if (i >= call_param_types.size()) (*error_count)++; + } + } + +} + +/* a helper function... */ +symbol_c *fill_candidate_datatypes_c::base_type(symbol_c *symbol) { + /* NOTE: symbol == NULL is valid. It will occur when, for e.g., an undefined/undeclared symbolic_variable is used + * in the code. + */ + if (symbol == NULL) return NULL; + return (symbol_c *)symbol->accept(search_base_type); +} + +/*********************/ +/* B 1.2 - Constants */ +/*********************/ +/******************************/ +/* B 1.2.1 - Numeric Literals */ +/******************************/ +void *fill_candidate_datatypes_c::visit(real_c *symbol) { + int calc_size; + + calc_size = sizeoftype(symbol); + if (calc_size <= sizeoftype(&search_constant_type_c::real_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::real_type_name); + if (calc_size <= sizeoftype(&search_constant_type_c::real_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::lreal_type_name); + if (debug) std::cout << "ANY_REAL [" << symbol->candidate_datatypes.size() << "]" << std::endl; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(integer_c *symbol) { + int calc_size; + + calc_size = sizeoftype(symbol); + if (calc_size <= sizeoftype(&search_constant_type_c::bool_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name); + if (calc_size <= sizeoftype(&search_constant_type_c::byte_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::byte_type_name); + if (calc_size <= sizeoftype(&search_constant_type_c::word_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::word_type_name); + if (calc_size <= sizeoftype(&search_constant_type_c::dword_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::dword_type_name); + if (calc_size <= sizeoftype(&search_constant_type_c::lword_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::lword_type_name); + + if (calc_size < sizeoftype(&search_constant_type_c::sint_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::sint_type_name); + if (calc_size < sizeoftype(&search_constant_type_c::int_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::int_type_name); + if (calc_size < sizeoftype(&search_constant_type_c::dint_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::dint_type_name); + if (calc_size < sizeoftype(&search_constant_type_c::lint_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::lint_type_name); + if (calc_size <= sizeoftype(&search_constant_type_c::usint_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::usint_type_name); + if (calc_size <= sizeoftype(&search_constant_type_c::uint_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::uint_type_name); + if (calc_size <= sizeoftype(&search_constant_type_c::udint_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::udint_type_name); + if (calc_size <= sizeoftype(&search_constant_type_c::ulint_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::ulint_type_name); + if (debug) std::cout << "ANY_INT [" << symbol->candidate_datatypes.size()<< "]" << std::endl; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(neg_real_c *symbol) { + if (sizeoftype(symbol) <= sizeoftype(&search_constant_type_c::real_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::real_type_name); + symbol->candidate_datatypes.push_back(&search_constant_type_c::lreal_type_name); + if (debug) std::cout << "neg ANY_REAL [" << symbol->candidate_datatypes.size() << "]" << std::endl; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(neg_integer_c *symbol) { + int calc_size; + + calc_size = sizeoftype(symbol); + if (calc_size <= sizeoftype(&search_constant_type_c::int_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::int_type_name); + if (calc_size <= sizeoftype(&search_constant_type_c::sint_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::sint_type_name); + if (calc_size <= sizeoftype(&search_constant_type_c::dint_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::dint_type_name); + if (calc_size <= sizeoftype(&search_constant_type_c::lint_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::lint_type_name); + if (debug) std::cout << "neg ANY_INT [" << symbol->candidate_datatypes.size() << "]" << std::endl; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(binary_integer_c *symbol) { + int calc_size; + + calc_size = sizeoftype(symbol); + if (calc_size <= sizeoftype(&search_constant_type_c::bool_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name); + if (calc_size <= sizeoftype(&search_constant_type_c::byte_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::byte_type_name); + if (calc_size <= sizeoftype(&search_constant_type_c::word_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::word_type_name); + if (calc_size <= sizeoftype(&search_constant_type_c::dword_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::dword_type_name); + if (calc_size <= sizeoftype(&search_constant_type_c::lword_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::lword_type_name); + + if (calc_size < sizeoftype(&search_constant_type_c::sint_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::sint_type_name); + if (calc_size < sizeoftype(&search_constant_type_c::int_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::int_type_name); + if (calc_size < sizeoftype(&search_constant_type_c::dint_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::dint_type_name); + if (calc_size < sizeoftype(&search_constant_type_c::lint_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::lint_type_name); + if (calc_size <= sizeoftype(&search_constant_type_c::usint_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::usint_type_name); + if (calc_size <= sizeoftype(&search_constant_type_c::uint_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::uint_type_name); + if (calc_size <= sizeoftype(&search_constant_type_c::udint_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::udint_type_name); + if (calc_size <= sizeoftype(&search_constant_type_c::ulint_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::ulint_type_name); + if (debug) std::cout << "ANY_INT [" << symbol->candidate_datatypes.size()<< "]" << std::endl; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(octal_integer_c *symbol) { + int calc_size; + + calc_size = sizeoftype(symbol); + if (calc_size <= sizeoftype(&search_constant_type_c::bool_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name); + if (calc_size <= sizeoftype(&search_constant_type_c::byte_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::byte_type_name); + if (calc_size <= sizeoftype(&search_constant_type_c::word_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::word_type_name); + if (calc_size <= sizeoftype(&search_constant_type_c::dword_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::dword_type_name); + if (calc_size <= sizeoftype(&search_constant_type_c::lword_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::lword_type_name); + + if (calc_size < sizeoftype(&search_constant_type_c::sint_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::sint_type_name); + if (calc_size < sizeoftype(&search_constant_type_c::int_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::int_type_name); + if (calc_size < sizeoftype(&search_constant_type_c::dint_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::dint_type_name); + if (calc_size < sizeoftype(&search_constant_type_c::lint_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::lint_type_name); + if (calc_size <= sizeoftype(&search_constant_type_c::usint_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::usint_type_name); + if (calc_size <= sizeoftype(&search_constant_type_c::uint_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::uint_type_name); + if (calc_size <= sizeoftype(&search_constant_type_c::udint_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::udint_type_name); + if (calc_size <= sizeoftype(&search_constant_type_c::ulint_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::ulint_type_name); + if (debug) std::cout << "ANY_INT [" << symbol->candidate_datatypes.size()<< "]" << std::endl; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(hex_integer_c *symbol) { + int calc_size; + + calc_size = sizeoftype(symbol); + if (calc_size <= sizeoftype(&search_constant_type_c::bool_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name); + if (calc_size <= sizeoftype(&search_constant_type_c::byte_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::byte_type_name); + if (calc_size <= sizeoftype(&search_constant_type_c::word_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::word_type_name); + if (calc_size <= sizeoftype(&search_constant_type_c::dword_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::dword_type_name); + if (calc_size <= sizeoftype(&search_constant_type_c::lword_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::lword_type_name); + + if (calc_size < sizeoftype(&search_constant_type_c::sint_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::sint_type_name); + if (calc_size < sizeoftype(&search_constant_type_c::int_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::int_type_name); + if (calc_size < sizeoftype(&search_constant_type_c::dint_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::dint_type_name); + if (calc_size < sizeoftype(&search_constant_type_c::lint_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::lint_type_name); + if (calc_size <= sizeoftype(&search_constant_type_c::usint_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::usint_type_name); + if (calc_size <= sizeoftype(&search_constant_type_c::uint_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::uint_type_name); + if (calc_size <= sizeoftype(&search_constant_type_c::udint_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::udint_type_name); + if (calc_size <= sizeoftype(&search_constant_type_c::ulint_type_name)) + symbol->candidate_datatypes.push_back(&search_constant_type_c::ulint_type_name); + if (debug) std::cout << "ANY_INT [" << symbol->candidate_datatypes.size()<< "]" << std::endl; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(integer_literal_c *symbol) { + symbol->candidate_datatypes.push_back(symbol->type); + if (debug) std::cout << "INT_LITERAL [" << symbol->candidate_datatypes.size() << "]\n"; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(real_literal_c *symbol) { + symbol->candidate_datatypes.push_back(symbol->type); + if (debug) std::cout << "REAL_LITERAL [" << symbol->candidate_datatypes.size() << "]\n"; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(bit_string_literal_c *symbol) { + symbol->candidate_datatypes.push_back(symbol->type); + return NULL; +} + +void *fill_candidate_datatypes_c::visit(boolean_literal_c *symbol) { + symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name); + return NULL; +} + +void *fill_candidate_datatypes_c::visit(boolean_true_c *symbol) { + symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name); + return NULL; +} + +void *fill_candidate_datatypes_c::visit(boolean_false_c *symbol) { + symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name); + return NULL; +} + +/*******************************/ +/* B.1.2.2 Character Strings */ +/*******************************/ +void *fill_candidate_datatypes_c::visit(double_byte_character_string_c *symbol) { + symbol->candidate_datatypes.push_back(&search_constant_type_c::wstring_type_name); + return NULL; +} + +void *fill_candidate_datatypes_c::visit(single_byte_character_string_c *symbol) { + symbol->candidate_datatypes.push_back(&search_constant_type_c::string_type_name); + return NULL; +} + +/***************************/ +/* B 1.2.3 - Time Literals */ +/***************************/ +/************************/ +/* B 1.2.3.1 - Duration */ +/************************/ +void *fill_candidate_datatypes_c::visit(duration_c *symbol) { + symbol->candidate_datatypes.push_back(symbol->type_name); + if (debug) std::cout << "TIME_LITERAL [" << symbol->candidate_datatypes.size() << "]\n"; + return NULL; +} + +/************************************/ +/* B 1.2.3.2 - Time of day and Date */ +/************************************/ +void *fill_candidate_datatypes_c::visit(time_of_day_c *symbol) { + symbol->candidate_datatypes.push_back(symbol->type_name); + return NULL; +} + +void *fill_candidate_datatypes_c::visit(date_c *symbol) { + symbol->candidate_datatypes.push_back(symbol->type_name); + return NULL; +} + +void *fill_candidate_datatypes_c::visit(date_and_time_c *symbol) { + symbol->candidate_datatypes.push_back(symbol->type_name); + return NULL; +} + +/**********************/ +/* B 1.3 - Data types */ +/**********************/ +/********************************/ +/* B 1.3.3 - Derived data types */ +/********************************/ +/* signed_integer DOTDOT signed_integer */ +// SYM_REF2(subrange_c, lower_limit, upper_limit) +void *fill_candidate_datatypes_c::visit(subrange_c *symbol) { + symbol->lower_limit->accept(*this); + symbol->upper_limit->accept(*this); + + for (unsigned int u = 0; u < symbol->upper_limit->candidate_datatypes.size(); u++) { + for(unsigned int l = 0; l < symbol->lower_limit->candidate_datatypes.size(); l++) { + if (is_type_equal(symbol->upper_limit->candidate_datatypes[u], symbol->lower_limit->candidate_datatypes[l])) + symbol->candidate_datatypes.push_back(symbol->lower_limit->candidate_datatypes[l]); + } + } + return NULL; +} + + +void *fill_candidate_datatypes_c::visit(data_type_declaration_c *symbol) { + // TODO !!! + /* for the moment we must return NULL so semantic analysis of remaining code is not interrupted! */ + return NULL; +} + +void *fill_candidate_datatypes_c::visit(enumerated_value_c *symbol) { + symbol_c *enumerated_type; + + if (NULL != symbol->type) + enumerated_type = symbol->type; + else { + enumerated_type = enumerated_value_symtable.find_value(symbol->value); + if (enumerated_type == enumerated_value_symtable.end_value()) + enumerated_type = NULL; + } + enumerated_type = base_type(enumerated_type); + if (NULL != enumerated_type) + symbol->candidate_datatypes.push_back(enumerated_type); + + if (debug) std::cout << "ENUMERATE [" << symbol->candidate_datatypes.size() << "]\n"; + return NULL; +} + + +/*********************/ +/* B 1.4 - Variables */ +/*********************/ +void *fill_candidate_datatypes_c::visit(symbolic_variable_c *symbol) { + symbol_c *result = search_varfb_instance_type->get_basetype_decl(symbol); + if (NULL != result) + symbol->candidate_datatypes.push_back(result); + if (debug) std::cout << "VAR [" << symbol->candidate_datatypes.size() << "]\n"; + return NULL; +} + +/********************************************/ +/* B 1.4.1 - Directly Represented Variables */ +/********************************************/ +void *fill_candidate_datatypes_c::visit(direct_variable_c *symbol) { + /* Comment added by mario: + * The following code is safe, actually, as the lexical parser guarantees the correct IEC61131-3 syntax was used. + */ + /* However, we should probably add an assertion in case we later change the lexical parser! */ + /* if (symbol->value == NULL) ERROR; + * if (symbol->value[0] == '\0') ERROR; + * if (symbol->value[1] == '\0') ERROR; + */ + switch (symbol->value[2]) { + case 'X': // bit - 1 bit + symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name); + break; + + case 'B': // byte - 8 bits + symbol->candidate_datatypes.push_back(&search_constant_type_c::byte_type_name); + break; + + case 'W': // word - 16 bits + symbol->candidate_datatypes.push_back(&search_constant_type_c::word_type_name); + break; + + case 'D': // double word - 32 bits + symbol->candidate_datatypes.push_back(&search_constant_type_c::dword_type_name); + break; + + case 'L': // long word - 64 bits + symbol->candidate_datatypes.push_back(&search_constant_type_c::lword_type_name); + break; + + default: // if none of the above, then the empty string was used <=> boolean + symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name); + break; + } + return NULL; +} + +/*************************************/ +/* B 1.4.2 - Multi-element variables */ +/*************************************/ +/* subscripted_variable '[' subscript_list ']' */ +// SYM_REF2(array_variable_c, subscripted_variable, subscript_list) +void *fill_candidate_datatypes_c::visit(array_variable_c *symbol) { + /* get the declaration of the data type __stored__ in the array... */ + /* if we were to want the data type of the array itself, then we should call_param_name + * search_varfb_instance_type->get_basetype_decl(symbol->subscripted_variable) + */ + symbol_c *result = search_varfb_instance_type->get_basetype_decl(symbol); + if (NULL != result) symbol->candidate_datatypes.push_back(result); + + /* recursively call the subscript list, so we can check the data types of the expressions used for the subscripts */ +if (debug) std::cout << "ARRAY_VAR XXX\n"; + symbol->subscript_list->accept(*this); +if (debug) std::cout << "ARRAY_VAR YYY\n"; + + if (debug) std::cout << "ARRAY_VAR [" << symbol->candidate_datatypes.size() << "]\n"; + return NULL; +} + + +/* subscript_list ',' subscript */ +// SYM_LIST(subscript_list_c) +/* NOTE: we inherit from iterator visitor, so we do not need to implement this method... */ +#if 0 +void *fill_candidate_datatypes_c::visit(subscript_list_c *symbol) { +} +#endif + + +/* record_variable '.' field_selector */ +/* WARNING: input and/or output variables of function blocks + * may be accessed as fields of a structured variable! + * Code handling a structured_variable_c must take + * this into account! + */ +// SYM_REF2(structured_variable_c, record_variable, field_selector) +/* NOTE: We do not need to recursively determine the data types of each field_selector, as the search_varfb_instance_type + * will do that for us. So we determine the candidate datatypes only for the full structured_variable. + */ +void *fill_candidate_datatypes_c::visit(structured_variable_c *symbol) { + symbol_c *result = search_varfb_instance_type->get_basetype_decl(symbol); + if (NULL != result) symbol->candidate_datatypes.push_back(result); + return NULL; +} + +/************************************/ +/* B 1.5 Program organization units */ +/************************************/ +/*********************/ +/* B 1.5.1 Functions */ +/*********************/ +void *fill_candidate_datatypes_c::visit(function_declaration_c *symbol) { + search_varfb_instance_type = new search_varfb_instance_type_c(symbol); + symbol->var_declarations_list->accept(*this); + if (debug) printf("Filling candidate data types list in body of function %s\n", ((token_c *)(symbol->derived_function_name))->value); + il_parenthesis_level = 0; + prev_il_instruction = NULL; + symbol->function_body->accept(*this); + prev_il_instruction = NULL; + delete search_varfb_instance_type; + search_varfb_instance_type = NULL; + return NULL; +} + +/***************************/ +/* B 1.5.2 Function blocks */ +/***************************/ +void *fill_candidate_datatypes_c::visit(function_block_declaration_c *symbol) { + search_varfb_instance_type = new search_varfb_instance_type_c(symbol); + symbol->var_declarations->accept(*this); + if (debug) printf("Filling candidate data types list in body of FB %s\n", ((token_c *)(symbol->fblock_name))->value); + il_parenthesis_level = 0; + prev_il_instruction = NULL; + symbol->fblock_body->accept(*this); + prev_il_instruction = NULL; + delete search_varfb_instance_type; + search_varfb_instance_type = NULL; + return NULL; +} + +/**********************/ +/* B 1.5.3 - Programs */ +/**********************/ +void *fill_candidate_datatypes_c::visit(program_declaration_c *symbol) { + search_varfb_instance_type = new search_varfb_instance_type_c(symbol); + symbol->var_declarations->accept(*this); + if (debug) printf("Filling candidate data types list in body of program %s\n", ((token_c *)(symbol->program_type_name))->value); + il_parenthesis_level = 0; + prev_il_instruction = NULL; + symbol->function_block_body->accept(*this); + prev_il_instruction = NULL; + delete search_varfb_instance_type; + search_varfb_instance_type = NULL; + return NULL; +} + + + +/********************************/ +/* B 1.7 Configuration elements */ +/********************************/ +void *fill_candidate_datatypes_c::visit(configuration_declaration_c *symbol) { +#if 0 + // TODO !!! + /* for the moment we must return NULL so semantic analysis of remaining code is not interrupted! */ +#endif + return NULL; +} + +/****************************************/ +/* B.2 - Language IL (Instruction List) */ +/****************************************/ +/***********************************/ +/* B 2.1 Instructions and Operands */ +/***********************************/ +// void *visit(instruction_list_c *symbol); +void *fill_candidate_datatypes_c::visit(il_simple_operation_c *symbol) { + /* determine the data type of the operand */ + if (NULL != symbol->il_operand) { + symbol->il_operand->accept(*this); + } + /* recursive call to fill the candidate data types list */ + il_operand = symbol->il_operand; + symbol->il_simple_operator->accept(*this); + il_operand = NULL; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(il_function_call_c *symbol) { +} + +/* MJS: Manuele, could you please not delete the following 2 lines of comments. They help me understand where this class is used + * and when it is created by bison - syntax parse, and how it can show up in the abstract syntax tree. + * + * Actually, it could be helpful if we could have all the similar comments already present in visit_expression_type_c + * in the 3 new classes fill/narrow/print candidate datatype + */ +/* | il_expr_operator '(' [il_operand] eol_list [simple_instr_list] ')' */ +// SYM_REF3(il_expression_c, il_expr_operator, il_operand, simple_instr_list); +void *fill_candidate_datatypes_c::visit(il_expression_c *symbol) { + if (NULL != symbol->il_operand) + symbol->il_operand->accept(*this); + + il_parenthesis_level++; + + /* Note that prev_il_instruction will actually be used to get the current value store in the il_default_variable */ + /* If a symbol->il_operand is provided, then that will be the result before executing the simple_instr_list. + * If this symbol is NULL, then the current result is also NULL, which is correct for what we want to do! + */ + symbol_c *prev_il_instruction_backup = prev_il_instruction; + prev_il_instruction = symbol->il_operand; + + if(symbol->simple_instr_list != NULL) { + symbol->simple_instr_list->accept(*this); + } + + il_parenthesis_level--; + if (il_parenthesis_level < 0) ERROR; + + /* Now check the if the data type semantics of operation are correct, */ + il_operand = prev_il_instruction; + prev_il_instruction = prev_il_instruction_backup; + symbol->il_expr_operator->accept(*this); + il_operand = NULL; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(il_jump_operation_c *symbol) { + /* recursive call to fill the candidate data types list */ + il_operand = NULL; + symbol->il_jump_operator->accept(*this); + il_operand = NULL; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(il_fb_call_c *symbol) { +} + +void *fill_candidate_datatypes_c::visit(il_formal_funct_call_c *symbol) { + +} + +/* + void *visit(il_operand_list_c *symbol); + void *visit(simple_instr_list_c *symbol); + void *visit(il_param_list_c *symbol); + void *visit(il_param_assignment_c *symbol); + void *visit(il_param_out_assignment_c *symbol); +*/ + +/*******************/ +/* B 2.2 Operators */ +/*******************/ +void *fill_candidate_datatypes_c::visit(LD_operator_c *symbol) { + for(unsigned int i = 0; i < il_operand->candidate_datatypes.size(); i++) { + symbol->candidate_datatypes.push_back(il_operand->candidate_datatypes[i]); + } + if (debug) std::cout << "LD [" << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(LDN_operator_c *symbol) { + for(unsigned int i = 0; i < il_operand->candidate_datatypes.size(); i++) { + if (is_ANY_BIT_compatible(il_operand->candidate_datatypes[i])) + symbol->candidate_datatypes.push_back(il_operand->candidate_datatypes[i]); + } + if (debug) std::cout << "LDN [" << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(ST_operator_c *symbol) { + symbol_c *prev_instruction_type, *operand_type; + + if (NULL == prev_il_instruction) return NULL; + for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) { + prev_instruction_type = prev_il_instruction->candidate_datatypes[i]; + operand_type = il_operand->candidate_datatypes[j]; + if (is_type_equal(prev_instruction_type,operand_type)) + symbol->candidate_datatypes.push_back(prev_instruction_type); + } + } + if (debug) std::cout << "ST [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(STN_operator_c *symbol) { + symbol_c *prev_instruction_type, *operand_type; + + if (NULL == prev_il_instruction) return NULL; + for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) { + prev_instruction_type = prev_il_instruction->candidate_datatypes[i]; + operand_type = il_operand->candidate_datatypes[j]; + if (is_type_equal(prev_instruction_type,operand_type) && is_ANY_BIT_compatible(il_operand->candidate_datatypes[i])) + symbol->candidate_datatypes.push_back(prev_instruction_type); + } + } + if (debug) std::cout << "STN [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(NOT_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(S_operator_c *symbol) { + symbol_c *prev_instruction_type, *operand_type; + + if (NULL == prev_il_instruction) return NULL; + for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) { + prev_instruction_type = prev_il_instruction->candidate_datatypes[i]; + operand_type = il_operand->candidate_datatypes[j]; + if (is_type_equal(prev_instruction_type,operand_type) && is_ANY_BOOL_compatible(il_operand->candidate_datatypes[i])) + symbol->candidate_datatypes.push_back(prev_instruction_type); + } + } + if (debug) std::cout << "S [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(R_operator_c *symbol) { + symbol_c *prev_instruction_type, *operand_type; + + if (NULL == prev_il_instruction) return NULL; + for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) { + prev_instruction_type = prev_il_instruction->candidate_datatypes[i]; + operand_type = il_operand->candidate_datatypes[j]; + if (is_type_equal(prev_instruction_type,operand_type) && is_ANY_BOOL_compatible(il_operand->candidate_datatypes[i])) + symbol->candidate_datatypes.push_back(prev_instruction_type); + } + } + if (debug) std::cout << "R [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(S1_operator_c *symbol) { + symbol_c *prev_instruction_type, *operand_type; + + if (NULL == prev_il_instruction) return NULL; + for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) { + prev_instruction_type = prev_il_instruction->candidate_datatypes[i]; + operand_type = il_operand->candidate_datatypes[j]; + if (is_type_equal(prev_instruction_type,operand_type) && is_ANY_BOOL_compatible(il_operand->candidate_datatypes[i])) + symbol->candidate_datatypes.push_back(prev_instruction_type); + } + } + if (debug) std::cout << "S1 [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(R1_operator_c *symbol) { + symbol_c *prev_instruction_type, *operand_type; + + if (NULL == prev_il_instruction) return NULL; + for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) { + prev_instruction_type = prev_il_instruction->candidate_datatypes[i]; + operand_type = il_operand->candidate_datatypes[j]; + if (is_type_equal(prev_instruction_type,operand_type) && is_ANY_BOOL_compatible(il_operand->candidate_datatypes[i])) + symbol->candidate_datatypes.push_back(prev_instruction_type); + } + } + if (debug) std::cout << "R1 [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(CLK_operator_c *symbol) { + /* MANU: + * How it works? I(MANU) don't know this function + */ + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(CU_operator_c *symbol) { + /* MANU: + * How it works? I(MANU) don't know this function + */ + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(CD_operator_c *symbol) { + /* MANU: + * How it works? I(MANU) don't know this function + */ + + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(PV_operator_c *symbol) { + /* MANU: + * How it works? I(MANU) don't know this function + */ + + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(IN_operator_c *symbol) { + /* MANU: + * How it works? I(MANU) don't know this function + */ + + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(PT_operator_c *symbol) { + /* MANU: + * How it works? I(MANU) don't know this function + */ + + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(AND_operator_c *symbol) { + symbol_c *prev_instruction_type, *operand_type; + + if (NULL == prev_il_instruction) return NULL; + for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) { + prev_instruction_type = prev_il_instruction->candidate_datatypes[i]; + operand_type = il_operand->candidate_datatypes[j]; + if (is_type_equal(prev_instruction_type, operand_type) && + is_ANY_BIT_compatible(operand_type)) + symbol->candidate_datatypes.push_back(prev_instruction_type); + } + } + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(OR_operator_c *symbol) { + symbol_c *prev_instruction_type, *operand_type; + + if (NULL == prev_il_instruction) return NULL; + for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) { + prev_instruction_type = prev_il_instruction->candidate_datatypes[i]; + operand_type = il_operand->candidate_datatypes[j]; + if (is_type_equal(prev_instruction_type, operand_type) && + is_ANY_BIT_compatible(operand_type)) + symbol->candidate_datatypes.push_back(prev_instruction_type); + } + } + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(XOR_operator_c *symbol) { + symbol_c *prev_instruction_type, *operand_type; + + if (NULL == prev_il_instruction) return NULL; + for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) { + prev_instruction_type = prev_il_instruction->candidate_datatypes[i]; + operand_type = il_operand->candidate_datatypes[j]; + if (is_type_equal(prev_instruction_type, operand_type) && + is_ANY_BIT_compatible(operand_type)) + symbol->candidate_datatypes.push_back(prev_instruction_type); + } + } + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(ANDN_operator_c *symbol) { + symbol_c *prev_instruction_type, *operand_type; + + if (NULL == prev_il_instruction) return NULL; + for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) { + prev_instruction_type = prev_il_instruction->candidate_datatypes[i]; + operand_type = il_operand->candidate_datatypes[j]; + if (is_type_equal(prev_instruction_type, operand_type) && + is_ANY_BIT_compatible(operand_type)) + symbol->candidate_datatypes.push_back(prev_instruction_type); + } + } + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(ORN_operator_c *symbol) { + symbol_c *prev_instruction_type, *operand_type; + + if (NULL == prev_il_instruction) return NULL; + for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) { + prev_instruction_type = prev_il_instruction->candidate_datatypes[i]; + operand_type = il_operand->candidate_datatypes[j]; + if (is_type_equal(prev_instruction_type, operand_type) && + is_ANY_BIT_compatible(operand_type)) + symbol->candidate_datatypes.push_back(prev_instruction_type); + } + } + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(XORN_operator_c *symbol) { + symbol_c *prev_instruction_type, *operand_type; + + if (NULL == prev_il_instruction) return NULL; + for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) { + prev_instruction_type = prev_il_instruction->candidate_datatypes[i]; + operand_type = il_operand->candidate_datatypes[j]; + if (is_type_equal(prev_instruction_type, operand_type) && + is_ANY_BIT_compatible(operand_type)) + symbol->candidate_datatypes.push_back(prev_instruction_type); + } + } + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(ADD_operator_c *symbol) { + symbol_c *prev_instruction_type, *operand_type; + + if (NULL == prev_il_instruction) return NULL; + for(unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) { + prev_instruction_type = prev_il_instruction->candidate_datatypes[i]; + operand_type = il_operand->candidate_datatypes[j]; + if (is_type_equal(prev_instruction_type, operand_type) && + is_ANY_NUM_compatible(prev_instruction_type)) + symbol->candidate_datatypes.push_back(prev_instruction_type); + else { + symbol_c *result = widening_conversion(prev_instruction_type, operand_type, widen_ADD_table); + if (result) + symbol->candidate_datatypes.push_back(result); + + } + } + } + if (debug) std::cout << "ADD [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(SUB_operator_c *symbol) { + symbol_c *prev_instruction_type, *operand_type; + + if (NULL == prev_il_instruction) return NULL; + for(unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) { + prev_instruction_type = prev_il_instruction->candidate_datatypes[i]; + operand_type = il_operand->candidate_datatypes[j]; + if (is_type_equal(prev_instruction_type, operand_type) && + is_ANY_NUM_compatible(prev_instruction_type)) + symbol->candidate_datatypes.push_back(prev_instruction_type); + else { + symbol_c *result = widening_conversion(prev_instruction_type, operand_type, widen_SUB_table); + if (result) + symbol->candidate_datatypes.push_back(result); + } + } + } + if (debug) std::cout << "SUB [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(MUL_operator_c *symbol) { + symbol_c *prev_instruction_type, *operand_type; + + if (NULL == prev_il_instruction) return NULL; + for(unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) { + prev_instruction_type = prev_il_instruction->candidate_datatypes[i]; + operand_type = il_operand->candidate_datatypes[j]; + if (is_type_equal(prev_instruction_type, operand_type) && + is_ANY_NUM_compatible(prev_instruction_type)) + symbol->candidate_datatypes.push_back(prev_instruction_type); + else { + symbol_c *result = widening_conversion(prev_instruction_type, operand_type, widen_MUL_table); + if (result) + symbol->candidate_datatypes.push_back(result); + } + } + } + if (debug) std::cout << "MUL [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(DIV_operator_c *symbol) { + symbol_c *prev_instruction_type, *operand_type; + + if (NULL == prev_il_instruction) return NULL; + for(unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) { + prev_instruction_type = prev_il_instruction->candidate_datatypes[i]; + operand_type = il_operand->candidate_datatypes[j]; + if (is_type_equal(prev_instruction_type, operand_type) && + is_ANY_NUM_compatible(prev_instruction_type)) + symbol->candidate_datatypes.push_back(prev_instruction_type); + else { + symbol_c *result = widening_conversion(prev_instruction_type, operand_type, widen_DIV_table); + if (result) + symbol->candidate_datatypes.push_back(result); + } + } + } + if (debug) std::cout << "DIV [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(MOD_operator_c *symbol) { + symbol_c *prev_instruction_type, *operand_type; + + if (NULL == prev_il_instruction) return NULL; + for(unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) { + prev_instruction_type = prev_il_instruction->candidate_datatypes[i]; + operand_type = il_operand->candidate_datatypes[j]; + if (is_type_equal(prev_instruction_type, operand_type) && + is_ANY_INT_compatible(prev_instruction_type)) + symbol->candidate_datatypes.push_back(prev_instruction_type); + } + } + if (debug) std::cout << "MOD [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(GT_operator_c *symbol) { + bool found = false; + + if (NULL == prev_il_instruction) return NULL; + for(unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) { + if (is_type_equal(prev_il_instruction->candidate_datatypes[i], il_operand->candidate_datatypes[j]) + && is_ANY_ELEMENTARY_compatible(prev_il_instruction->candidate_datatypes[i])) { + found = true; + break; + } + } + } + if (found) symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name); + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(GE_operator_c *symbol) { + bool found = false; + + if (NULL == prev_il_instruction) return NULL; + for(unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) { + if (is_type_equal(prev_il_instruction->candidate_datatypes[i], il_operand->candidate_datatypes[j]) + && is_ANY_ELEMENTARY_compatible(prev_il_instruction->candidate_datatypes[i])) { + found = true; + break; + } + } + } + if (found) symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name); + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(EQ_operator_c *symbol) { + bool found = false; + + if (NULL == prev_il_instruction) return NULL; + for(unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) { + if (is_type_equal(prev_il_instruction->candidate_datatypes[i], il_operand->candidate_datatypes[j]) + && is_ANY_ELEMENTARY_compatible(prev_il_instruction->candidate_datatypes[i])) { + found = true; + break; + } + } + } + if (found) symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name); + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(LT_operator_c *symbol) { + bool found = false; + + if (NULL == prev_il_instruction) return NULL; + for(unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) { + if (is_type_equal(prev_il_instruction->candidate_datatypes[i], il_operand->candidate_datatypes[j]) + && is_ANY_ELEMENTARY_compatible(prev_il_instruction->candidate_datatypes[i])) { + found = true; + break; + } + } + } + if (found) symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name); + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(LE_operator_c *symbol) { + bool found = false; + + if (NULL == prev_il_instruction) return NULL; + for(unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) { + if (is_type_equal(prev_il_instruction->candidate_datatypes[i], il_operand->candidate_datatypes[j]) + && is_ANY_ELEMENTARY_compatible(prev_il_instruction->candidate_datatypes[i])) { + found = true; + break; + } + } + } + if (found) symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name); + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(NE_operator_c *symbol) { + bool found = false; + + if (NULL == prev_il_instruction) return NULL; + for(unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) { + if (is_type_equal(prev_il_instruction->candidate_datatypes[i], il_operand->candidate_datatypes[j]) + && is_ANY_ELEMENTARY_compatible(prev_il_instruction->candidate_datatypes[i])) { + found = true; + break; + } + } + } + if (found) symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name); + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(CAL_operator_c *symbol) { + if (NULL == prev_il_instruction) return NULL; + for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { + /* does not need to be bool type !! */ + symbol->candidate_datatypes.push_back(prev_il_instruction->candidate_datatypes[i]); + } + if (debug) std::cout << "CAL [" << prev_il_instruction->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(CALC_operator_c *symbol) { + if (NULL == prev_il_instruction) return NULL; + for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { + if (is_type(prev_il_instruction->candidate_datatypes[i], bool_type_name_c)) + symbol->candidate_datatypes.push_back(prev_il_instruction->candidate_datatypes[i]); + } + if (debug) std::cout << "CALC [" << prev_il_instruction->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(CALCN_operator_c *symbol) { + if (NULL == prev_il_instruction) return NULL; + for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { + if (is_type(prev_il_instruction->candidate_datatypes[i], bool_type_name_c)) + symbol->candidate_datatypes.push_back(prev_il_instruction->candidate_datatypes[i]); + } + if (debug) std::cout << "CALCN [" << prev_il_instruction->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(RET_operator_c *symbol) { + if (NULL == prev_il_instruction) return NULL; + for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { + /* does not need to be bool type !! */ + symbol->candidate_datatypes.push_back(prev_il_instruction->candidate_datatypes[i]); + } + if (debug) std::cout << "RET [" << prev_il_instruction->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(RETC_operator_c *symbol) { + if (NULL == prev_il_instruction) return NULL; + for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { + if (is_type(prev_il_instruction->candidate_datatypes[i], bool_type_name_c)) + symbol->candidate_datatypes.push_back(prev_il_instruction->candidate_datatypes[i]); + } + if (debug) std::cout << "RETC [" << prev_il_instruction->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(RETCN_operator_c *symbol) { + if (NULL == prev_il_instruction) return NULL; + for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { + if (is_type(prev_il_instruction->candidate_datatypes[i], bool_type_name_c)) + symbol->candidate_datatypes.push_back(prev_il_instruction->candidate_datatypes[i]); + } + if (debug) std::cout << "RETCN [" << prev_il_instruction->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(JMP_operator_c *symbol) { + if (NULL == prev_il_instruction) return NULL; + for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { + /* does not need to be bool type !! */ + symbol->candidate_datatypes.push_back(prev_il_instruction->candidate_datatypes[i]); + } + if (debug) std::cout << "JMP [" << prev_il_instruction->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(JMPC_operator_c *symbol) { + for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { + if (is_type(prev_il_instruction->candidate_datatypes[i], bool_type_name_c)) + symbol->candidate_datatypes.push_back(prev_il_instruction->candidate_datatypes[i]); + } + if (debug) std::cout << "JMPC [" << prev_il_instruction->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; + prev_il_instruction = symbol; + return NULL; +} + +void *fill_candidate_datatypes_c::visit(JMPCN_operator_c *symbol) { + for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) { + if (is_type(prev_il_instruction->candidate_datatypes[i], bool_type_name_c)) + symbol->candidate_datatypes.push_back(prev_il_instruction->candidate_datatypes[i]); + } + if (debug) std::cout << "JMPCN [" << prev_il_instruction->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; + prev_il_instruction = symbol; + return NULL; +} +/* Symbol class handled together with function call checks */ +// void *visit(il_assign_operator_c *symbol, variable_name); +/* Symbol class handled together with function call checks */ +// void *visit(il_assign_operator_c *symbol, option, variable_name); + +/***************************************/ +/* B.3 - Language ST (Structured Text) */ +/***************************************/ +/***********************/ +/* B 3.1 - Expressions */ +/***********************/ + +void *fill_candidate_datatypes_c::visit(or_expression_c *symbol) { + symbol->l_exp->accept(*this); + symbol->r_exp->accept(*this); + for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) { + for (unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) { + if (is_type_equal(symbol->l_exp->candidate_datatypes[i], symbol->r_exp->candidate_datatypes[j]) + && is_ANY_BIT_compatible(symbol->l_exp->candidate_datatypes[i])) + symbol->candidate_datatypes.push_back(symbol->l_exp->candidate_datatypes[i]); + } + } + return NULL; +} + + +void *fill_candidate_datatypes_c::visit(xor_expression_c *symbol) { + symbol->l_exp->accept(*this); + symbol->r_exp->accept(*this); + + for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) { + for (unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) { + if (is_type_equal(symbol->l_exp->candidate_datatypes[i], symbol->r_exp->candidate_datatypes[j]) + && is_ANY_BIT_compatible(symbol->l_exp->candidate_datatypes[i])) + symbol->candidate_datatypes.push_back(symbol->l_exp->candidate_datatypes[i]); + } + } + return NULL; +} + + +void *fill_candidate_datatypes_c::visit(and_expression_c *symbol) { + symbol->l_exp->accept(*this); + symbol->r_exp->accept(*this); + + for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) { + for (unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) { + if (is_type_equal(symbol->l_exp->candidate_datatypes[i], symbol->r_exp->candidate_datatypes[j]) + && is_ANY_BIT_compatible(symbol->l_exp->candidate_datatypes[i])) + symbol->candidate_datatypes.push_back(symbol->l_exp->candidate_datatypes[i]); + } + } + return NULL; +} + + +void *fill_candidate_datatypes_c::visit(equ_expression_c *symbol) { + symbol->l_exp->accept(*this); + symbol->r_exp->accept(*this); + bool found = false; + + for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) { + for (unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) { + if (is_type_equal(symbol->l_exp->candidate_datatypes[i], symbol->r_exp->candidate_datatypes[j]) + && is_ANY_ELEMENTARY_compatible(symbol->l_exp->candidate_datatypes[i])) { + found = true; + break; + } + } + } + if (found) symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name); + return NULL; +} + + +void *fill_candidate_datatypes_c::visit(notequ_expression_c *symbol) { + symbol->l_exp->accept(*this); + symbol->r_exp->accept(*this); + bool found = false; + + for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) { + for (unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) { + if (is_type_equal(symbol->l_exp->candidate_datatypes[i], symbol->r_exp->candidate_datatypes[j]) + && is_ANY_ELEMENTARY_compatible(symbol->l_exp->candidate_datatypes[i])) { + found = true; + break; + } + } + } + if (found) + symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name); + return NULL; +} + + +void *fill_candidate_datatypes_c::visit(lt_expression_c *symbol) { + symbol->l_exp->accept(*this); + symbol->r_exp->accept(*this); + bool found = false; + + for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) { + for (unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) { + if (is_type_equal(symbol->l_exp->candidate_datatypes[i], symbol->r_exp->candidate_datatypes[j]) + && is_ANY_ELEMENTARY_compatible(symbol->l_exp->candidate_datatypes[i])) { + found = true; + break; + } + } + } + if (found) + symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name); + return NULL; +} + + +void *fill_candidate_datatypes_c::visit(gt_expression_c *symbol) { + symbol->l_exp->accept(*this); + symbol->r_exp->accept(*this); + bool found = false; + + for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) { + for (unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) { + if (is_type_equal(symbol->l_exp->candidate_datatypes[i], symbol->r_exp->candidate_datatypes[j]) + && is_ANY_ELEMENTARY_compatible(symbol->l_exp->candidate_datatypes[i])) { + found = true; + break; + } + } + } + if (found) + symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name); + return NULL; +} + +void *fill_candidate_datatypes_c::visit(le_expression_c *symbol) { + symbol->l_exp->accept(*this); + symbol->r_exp->accept(*this); + bool found = false; + + for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) { + for (unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) { + if (is_type_equal(symbol->l_exp->candidate_datatypes[i], symbol->r_exp->candidate_datatypes[j]) + && is_ANY_ELEMENTARY_compatible(symbol->l_exp->candidate_datatypes[i])) { + found = true; + break; + } + } + } + if (found) + symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name); + return NULL; +} + +void *fill_candidate_datatypes_c::visit(ge_expression_c *symbol) { + symbol->l_exp->accept(*this); + symbol->r_exp->accept(*this); + bool found = false; + + for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) { + for (unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) { + if (is_type_equal(symbol->l_exp->candidate_datatypes[i], symbol->r_exp->candidate_datatypes[j]) + && is_ANY_ELEMENTARY_compatible(symbol->l_exp->candidate_datatypes[i])) { + found = true; + break; + } + } + } + if (found) + symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name); + return NULL; +} + +void *fill_candidate_datatypes_c::visit(add_expression_c *symbol) { + /* The following code is correct when handling the addition of 2 symbolic_variables + * In this case, adding two variables (e.g. USINT_var1 + USINT_var2) will always yield + * the same data type, even if the result of the adition could not fit inside the same + * data type (due to overflowing) + * + * However, when adding two literals (e.g. USINT#42 + USINT#3) + * we should be able to detect overflows of the result, and therefore not consider + * that the result may be of type USINT. + * Currently we do not yet detect these overflows, and allow handling the sum of two USINTs + * as always resulting in an USINT, even in the following expression + * (USINT#65535 + USINT#2). + * + * In the future we can add some code to reduce + * all the expressions that are based on literals into the resulting literal + * value (maybe some visitor class that will run before or after data type + * checking). Since this class will have to be very careful to make sure it implements the same mathematical + * details (e.g. how to round and truncate numbers) as defined in IEC 61131-3, we will leave this to the future. + * Also, the question will arise if we should also replace calls to standard + * functions if the input parameters are all literals (e.g. ADD(42, 42)). This + * means this class will be more difficult than it appears at first. + */ + symbol_c *left_type, *right_type; + + symbol->l_exp->accept(*this); + symbol->r_exp->accept(*this); + for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) { + left_type = symbol->l_exp->candidate_datatypes[i]; + right_type = symbol->r_exp->candidate_datatypes[j]; + if (is_type_equal(left_type, right_type) && is_ANY_NUM_compatible(left_type)) + symbol->candidate_datatypes.push_back(left_type); + else { + symbol_c *result = widening_conversion(left_type, right_type, widen_ADD_table); + if (result) + symbol->candidate_datatypes.push_back(result); + } + } + } + if (debug) std::cout << "+ [" << symbol->l_exp->candidate_datatypes.size() << "," << symbol->r_exp->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; + return NULL; +} + + +void *fill_candidate_datatypes_c::visit(sub_expression_c *symbol) { + symbol_c *left_type, *right_type; + + symbol->l_exp->accept(*this); + symbol->r_exp->accept(*this); + for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) { + left_type = symbol->l_exp->candidate_datatypes[i]; + right_type = symbol->r_exp->candidate_datatypes[j]; + if (is_type_equal(left_type, right_type) && is_ANY_NUM_compatible(left_type)) + symbol->candidate_datatypes.push_back(left_type); + else { + symbol_c *result = widening_conversion(left_type, right_type, widen_SUB_table); + if (result) + symbol->candidate_datatypes.push_back(result); + } + } + } + if (debug) std::cout << "- [" << symbol->l_exp->candidate_datatypes.size() << "," << symbol->r_exp->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; + return NULL; +} + + +void *fill_candidate_datatypes_c::visit(mul_expression_c *symbol) { + symbol_c *left_type, *right_type; + + symbol->l_exp->accept(*this); + symbol->r_exp->accept(*this); + for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) { + left_type = symbol->l_exp->candidate_datatypes[i]; + right_type = symbol->r_exp->candidate_datatypes[j]; + if (is_type_equal(left_type, right_type) && is_ANY_NUM_compatible(left_type)) + symbol->candidate_datatypes.push_back(left_type); + else { + symbol_c *result = widening_conversion(left_type, right_type, widen_MUL_table); + if (result) + symbol->candidate_datatypes.push_back(result); + } + + } + } + if (debug) std::cout << "* [" << symbol->l_exp->candidate_datatypes.size() << "," << symbol->r_exp->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; + + return NULL; +} + +void *fill_candidate_datatypes_c::visit(div_expression_c *symbol) { + symbol_c *left_type, *right_type; + + symbol->l_exp->accept(*this); + symbol->r_exp->accept(*this); + for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) { + left_type = symbol->l_exp->candidate_datatypes[i]; + right_type = symbol->r_exp->candidate_datatypes[j]; + if (is_type_equal(left_type, right_type) && is_ANY_NUM_type(left_type)) + symbol->candidate_datatypes.push_back(left_type); + else { + symbol_c *result = widening_conversion(left_type, right_type, widen_DIV_table); + if (result) + symbol->candidate_datatypes.push_back(result); + } + + } + } + if (debug) std::cout << "/ [" << symbol->l_exp->candidate_datatypes.size() << "," << symbol->r_exp->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; + return NULL; +} + + +void *fill_candidate_datatypes_c::visit(mod_expression_c *symbol) { + symbol_c *left_type, *right_type; + + symbol->l_exp->accept(*this); + symbol->r_exp->accept(*this); + for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) { + left_type = symbol->l_exp->candidate_datatypes[i]; + right_type = symbol->r_exp->candidate_datatypes[j]; + if (is_type_equal(left_type, right_type) && is_ANY_INT_compatible(left_type)) + symbol->candidate_datatypes.push_back(left_type); + } + } + if (debug) std::cout << "mod [" << symbol->l_exp->candidate_datatypes.size() << "," << symbol->r_exp->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; + return NULL; +} + + +void *fill_candidate_datatypes_c::visit(power_expression_c *symbol) { + symbol_c *left_type, *right_type; + bool check_ok; + + symbol->l_exp->accept(*this); + symbol->r_exp->accept(*this); + check_ok = false; + for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) { + left_type = symbol->l_exp->candidate_datatypes[i]; + if (is_ANY_REAL_compatible(left_type)) { + check_ok = true; + break; + } + } + if (! check_ok) return NULL; + check_ok = false; + for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) { + right_type = symbol->r_exp->candidate_datatypes[j]; + if (is_ANY_NUM_compatible(right_type)) { + check_ok = true; + break; + } + } + if (! check_ok) return NULL; + for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) { + symbol->candidate_datatypes.push_back(symbol->l_exp->candidate_datatypes[i]); + } + if (debug) std::cout << "** [" << symbol->l_exp->candidate_datatypes.size() << "," << symbol->r_exp->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; + return NULL; +} + + +void *fill_candidate_datatypes_c::visit(neg_expression_c *symbol) { + symbol->exp->accept(*this); + for (unsigned int i = 0; i < symbol->exp->candidate_datatypes.size(); i++) { + if (is_ANY_MAGNITUDE_compatible(symbol->exp->candidate_datatypes[i])) + symbol->candidate_datatypes.push_back(symbol->exp->candidate_datatypes[i]); + } + if (debug) std::cout << "neg [" << symbol->exp->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; + return NULL; +} + + +void *fill_candidate_datatypes_c::visit(not_expression_c *symbol) { + symbol->exp->accept(*this); + for (unsigned int i = 0; i < symbol->exp->candidate_datatypes.size(); i++) { + if (is_ANY_BIT_compatible(symbol->exp->candidate_datatypes[i])) + symbol->candidate_datatypes.push_back(symbol->exp->candidate_datatypes[i]); + } + if (debug) std::cout << "not [" << symbol->exp->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; + return NULL; +} + + +void *fill_candidate_datatypes_c::visit(function_invocation_c *symbol) { + function_declaration_c *f_decl; + list_c *parameter_list; + list_c *parameter_candidate_datatypes; + symbol_c *parameter_type; + int error_count; + function_symtable_t::iterator lower = function_symtable.lower_bound(symbol->function_name); + function_symtable_t::iterator upper = function_symtable.upper_bound(symbol->function_name); + + if (NULL != symbol->formal_param_list) + parameter_list = (list_c *)symbol->formal_param_list; + else if (NULL != symbol->nonformal_param_list) + parameter_list = (list_c *)symbol->nonformal_param_list; + else ERROR; + if (debug) std::cout << "function()\n"; + parameter_list->accept(*this); + for(; lower != upper; lower++) { + f_decl = function_symtable.get_value(lower); + error_count = 0; + /* Check if function declaration in symbol_table is compatible with parameters */ + if (NULL != symbol->nonformal_param_list) + /* nonformal parameter function call */ + match_nonformal_call(symbol, f_decl, &error_count); + else + /* formal parameter function call */ + match_formal_call (symbol, f_decl, &error_count); + if (0 == error_count) { + /* Add basetype matching function only if not present */ + unsigned int k; + parameter_type = base_type(f_decl->type_name); + for(k = 0; k < symbol->candidate_datatypes.size(); k++) { + if (is_type_equal(parameter_type, symbol->candidate_datatypes[k])) + break; + } + if (k >= symbol->candidate_datatypes.size()) + symbol->candidate_datatypes.push_back(parameter_type); + } + } + if (debug) std::cout << "end_function() [" << symbol->candidate_datatypes.size() << "] result.\n"; + return NULL; +} + +/********************/ +/* B 3.2 Statements */ +/********************/ +// SYM_LIST(statement_list_c) +/* The visitor of the base class search_visitor_c will handle calling each instruction in the list. + * We do not need to do anything here... + */ +// void *fill_candidate_datatypes_c::visit(statement_list_c *symbol) + + +/*********************************/ +/* B 3.2.1 Assignment Statements */ +/*********************************/ +void *fill_candidate_datatypes_c::visit(assignment_statement_c *symbol) { + symbol_c *left_type, *right_type; + + symbol->l_exp->accept(*this); + symbol->r_exp->accept(*this); + for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) { + left_type = symbol->l_exp->candidate_datatypes[i]; + right_type = symbol->r_exp->candidate_datatypes[j]; + if (is_type_equal(left_type, right_type)) + symbol->candidate_datatypes.push_back(left_type); + } + } + if (debug) std::cout << ":= [" << symbol->l_exp->candidate_datatypes.size() << "," << symbol->r_exp->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; + return NULL; +} + + + +/********************************/ +/* B 3.2.3 Selection Statements */ +/********************************/ +void *fill_candidate_datatypes_c::visit(if_statement_c *symbol) { + /* MANU: + * IF statement accept only BOOL type. We intersect with BOOL type to validate current if condition + * Example: + * IF 1 THEN ---> ok + * IF 5 THEN ---> not ok + * IF 1 OR 1 THEN ---> ok + * IF 1 OR 5 THEN ---> not ok + * IF SHL() THEN ---> ok if shl return BOOL + * IF INT_TO_REAL() ---> not ok + */ + symbol->expression->accept(*this); + if (NULL != symbol->statement_list) + symbol->statement_list->accept(*this); + if (NULL != symbol->elseif_statement_list) + symbol->elseif_statement_list->accept(*this); + if (NULL != symbol->else_statement_list) + symbol->else_statement_list->accept(*this); + return NULL; +} + + +void *fill_candidate_datatypes_c::visit(elseif_statement_c *symbol) { + symbol->expression->accept(*this); + if (NULL != symbol->statement_list) + symbol->statement_list->accept(*this); + return NULL; +} + +/* CASE expression OF case_element_list ELSE statement_list END_CASE */ +// SYM_REF3(case_statement_c, expression, case_element_list, statement_list) +void *fill_candidate_datatypes_c::visit(case_statement_c *symbol) { + symbol->expression->accept(*this); + if (NULL != symbol->case_element_list) + symbol->case_element_list->accept(*this); + if (NULL != symbol->statement_list) + symbol->statement_list->accept(*this); + return NULL; +} + + +/* helper symbol for case_statement */ +// SYM_LIST(case_element_list_c) +/* NOTE: visitor method for case_element_list_c is not required since we inherit from iterator_visitor_c */ + +/* case_list ':' statement_list */ +// SYM_REF2(case_element_c, case_list, statement_list) +/* NOTE: visitor method for case_element_c is not required since we inherit from iterator_visitor_c */ + +// SYM_LIST(case_list_c) +/* NOTE: visitor method for case_list_c is not required since we inherit from iterator_visitor_c */ + +/********************************/ +/* B 3.2.4 Iteration Statements */ +/********************************/ + +void *fill_candidate_datatypes_c::visit(for_statement_c *symbol) { + symbol->control_variable->accept(*this); + symbol->beg_expression->accept(*this); + symbol->end_expression->accept(*this); + if (NULL != symbol->by_expression) + symbol->by_expression->accept(*this); + if (NULL != symbol->statement_list) + symbol->statement_list->accept(*this); + return NULL; +} + + +void *fill_candidate_datatypes_c::visit(while_statement_c *symbol) { + symbol->expression->accept(*this); + if (NULL != symbol->statement_list) + symbol->statement_list->accept(*this); + return NULL; +} + + +void *fill_candidate_datatypes_c::visit(repeat_statement_c *symbol) { + symbol->expression->accept(*this); + if (NULL != symbol->statement_list) + symbol->statement_list->accept(*this); + return NULL; +} + + + + + + diff -r 0c2ef191b22a -r d48f53715f77 stage3/fill_candidate_datatypes.hh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stage3/fill_candidate_datatypes.hh Wed Feb 01 19:49:11 2012 +0000 @@ -0,0 +1,320 @@ +/* + * matiec - a compiler for the programming languages defined in IEC 61131-3 + * + * Copyright (C) 2009-2012 Mario de Sousa (msousa@fe.up.pt) + * Copyright (C) 2012 Manuele Conti (manuele.conti@sirius-es.it) + * Copyright (C) 2012 Matteo Facchinetti (matteo.facchinetti@sirius-es.it) + * + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * This code is made available on the understanding that it will not be + * used in safety-critical situations without a full and competent review. + */ + +/* + * An IEC 61131-3 compiler. + * + * Based on the + * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10) + * + */ + + +#include "../absyntax_utils/absyntax_utils.hh" + +class fill_candidate_datatypes_c: public iterator_visitor_c { + + private: + search_varfb_instance_type_c *search_varfb_instance_type; + search_base_type_c search_base_type; + /* When calling a function block, we must first find it's type, + * by searching through the declarations of the variables currently + * in scope. + * This class does just that... + * A new object instance is instantiated whenever we start checking semantics + * for a function block type declaration, or a program declaration. + * This object instance will then later be called while the + * function block's or the program's body is being handled. + * + * Note that functions cannot contain calls to function blocks, + * so we do not create an object instance when handling + * a function declaration. + */ + // search_var_instance_decl_c *search_var_instance_decl; + + /* This variable was created to pass information from + * fill_candidate_datatypes_c::visit(case_statement_c *symbol) function to + * fill_candidate_datatypes_c::visit(case_list_c *symbol) function. + */ + symbol_c *case_expression_type; + + /* In IL code, once we find a type mismatch error, it is best to + * ignore any further errors until the end of the logical operation, + * i.e. until the next LD. + * However, we cannot clear the il_error flag on all LD operations, + * as these may also be used within parenthesis. LD operations + * within parenthesis may not clear the error flag. + * We therefore need a counter to know how deep inside a parenthesis + * structure we are. + */ + int il_parenthesis_level; + bool error_found; + + /* the current data type of the data stored in the IL stack, i.e. the default variable */ + symbol_c *prev_il_instruction; + /* the current IL operand being analyzed - its symbol and its data type */ + symbol_c *il_operand_type; + symbol_c *il_operand; + symbol_c *widening_conversion(symbol_c *left_type, symbol_c *right_type, const struct widen_entry widen_table[]); + + public: + fill_candidate_datatypes_c(symbol_c *ignore); + virtual ~fill_candidate_datatypes_c(void); + + /* Match a function declaration with a function call through their parameters.*/ + void match_nonformal_call(symbol_c *f_call, symbol_c *f_decl, int *error_count = NULL); + void match_formal_call(symbol_c *f_call, symbol_c *f_decl, int *error_count = NULL); + + void *compute_standard_function_default(function_invocation_c *st_symbol, il_formal_funct_call_c *il_symbol); + void *compute_standard_function_il(il_function_call_c *symbol, symbol_c *param_data_type); + + /* a helper function... */ + symbol_c *base_type(symbol_c *symbol); + + /*********************/ + /* B 1.2 - Constants */ + /*********************/ + /******************************/ + /* B 1.2.1 - Numeric Literals */ + /******************************/ + void *visit(real_c *symbol); + void *visit(integer_c *symbol); + void *visit(neg_real_c *symbol); + void *visit(neg_integer_c *symbol); + void *visit(binary_integer_c *symbol); + void *visit(octal_integer_c *symbol); + void *visit(hex_integer_c *symbol); + void *visit(integer_literal_c *symbol); + void *visit(real_literal_c *symbol); + void *visit(bit_string_literal_c *symbol); + void *visit(boolean_literal_c *symbol); + void *visit(boolean_true_c *symbol); + void *visit(boolean_false_c *symbol); + + /*******************************/ + /* B.1.2.2 Character Strings */ + /*******************************/ + void *visit(double_byte_character_string_c *symbol); + void *visit(single_byte_character_string_c *symbol); + + /***************************/ + /* B 1.2.3 - Time Literals */ + /***************************/ + /************************/ + /* B 1.2.3.1 - Duration */ + /************************/ + void *visit(duration_c *symbol); + + /************************************/ + /* B 1.2.3.2 - Time of day and Date */ + /************************************/ + void *visit(time_of_day_c *symbol); + void *visit(date_c *symbol); + void *visit(date_and_time_c *symbol); + + + /**********************/ + /* B 1.3 - Data types */ + /**********************/ + /********************************/ + /* B 1.3.3 - Derived data types */ + /********************************/ + void *visit(subrange_c *symbol); + void *visit(data_type_declaration_c *symbol); + void *visit(enumerated_value_c *symbol); + + /*********************/ + /* B 1.4 - Variables */ + /*********************/ + void *visit(symbolic_variable_c *symbol); + + /********************************************/ + /* B 1.4.1 - Directly Represented Variables */ + /********************************************/ + void *visit(direct_variable_c *symbol); + + /*************************************/ + /* B 1.4.2 - Multi-element variables */ + /*************************************/ + void *visit(array_variable_c *symbol); + void *visit(structured_variable_c *symbol); + + /**************************************/ + /* B 1.5 - Program organization units */ + /**************************************/ + /***********************/ + /* B 1.5.1 - Functions */ + /***********************/ + void *visit(function_declaration_c *symbol); + + /*****************************/ + /* B 1.5.2 - Function blocks */ + /*****************************/ + void *visit(function_block_declaration_c *symbol); + + /**********************/ + /* B 1.5.3 - Programs */ + /**********************/ + void *visit(program_declaration_c *symbol); + + /********************************/ + /* B 1.7 Configuration elements */ + /********************************/ + void *visit(configuration_declaration_c *symbol); + + /****************************************/ + /* B.2 - Language IL (Instruction List) */ + /****************************************/ + /***********************************/ + /* B 2.1 Instructions and Operands */ + /***********************************/ + // void *visit(instruction_list_c *symbol); + void *visit(il_simple_operation_c *symbol); + void *visit(il_function_call_c *symbol); + void *visit(il_expression_c *symbol); + void *visit(il_jump_operation_c *symbol); + void *visit(il_fb_call_c *symbol); + void *visit(il_formal_funct_call_c *symbol); + /* + void *visit(il_operand_list_c *symbol); + void *visit(simple_instr_list_c *symbol); + void *visit(il_param_list_c *symbol); + void *visit(il_param_assignment_c *symbol); + void *visit(il_param_out_assignment_c *symbol); + */ + + /*******************/ + /* B 2.2 Operators */ + /*******************/ + void *visit(LD_operator_c *symbol); + void *visit(LDN_operator_c *symbol); + void *visit(ST_operator_c *symbol); + void *visit(STN_operator_c *symbol); + void *visit(NOT_operator_c *symbol); + void *visit(S_operator_c *symbol); + void *visit(R_operator_c *symbol); + void *visit(S1_operator_c *symbol); + void *visit(R1_operator_c *symbol); + void *visit(CLK_operator_c *symbol); + void *visit(CU_operator_c *symbol); + void *visit(CD_operator_c *symbol); + void *visit(PV_operator_c *symbol); + void *visit(IN_operator_c *symbol); + void *visit(PT_operator_c *symbol); + void *visit(AND_operator_c *symbol); + void *visit(OR_operator_c *symbol); + void *visit(XOR_operator_c *symbol); + void *visit(ANDN_operator_c *symbol); + void *visit(ORN_operator_c *symbol); + void *visit(XORN_operator_c *symbol); + void *visit(ADD_operator_c *symbol); + void *visit(SUB_operator_c *symbol); + void *visit(MUL_operator_c *symbol); + void *visit(DIV_operator_c *symbol); + void *visit(MOD_operator_c *symbol); + void *visit(GT_operator_c *symbol); + void *visit(GE_operator_c *symbol); + void *visit(EQ_operator_c *symbol); + void *visit(LT_operator_c *symbol); + void *visit(LE_operator_c *symbol); + void *visit(NE_operator_c *symbol); + void *visit(CAL_operator_c *symbol); + void *visit(CALC_operator_c *symbol); + void *visit(CALCN_operator_c *symbol); + void *visit(RET_operator_c *symbol); + void *visit(RETC_operator_c *symbol); + void *visit(RETCN_operator_c *symbol); + void *visit(JMP_operator_c *symbol); + void *visit(JMPC_operator_c *symbol); + void *visit(JMPCN_operator_c *symbol); + /* Symbol class handled together with function call checks */ + // void *visit(il_assign_operator_c *symbol, variable_name); + /* Symbol class handled together with function call checks */ + // void *visit(il_assign_operator_c *symbol, option, variable_name); + + + /***************************************/ + /* B.3 - Language ST (Structured Text) */ + /***************************************/ + /***********************/ + /* B 3.1 - Expressions */ + /***********************/ + void *visit(or_expression_c *symbol); + void *visit(xor_expression_c *symbol); + void *visit(and_expression_c *symbol); + void *visit(equ_expression_c *symbol); + void *visit(notequ_expression_c *symbol); + void *visit(lt_expression_c *symbol); + void *visit(gt_expression_c *symbol); + void *visit(le_expression_c *symbol); + void *visit(ge_expression_c *symbol); + void *visit(add_expression_c *symbol); + void *visit(sub_expression_c *symbol); + void *visit(mul_expression_c *symbol); + void *visit(div_expression_c *symbol); + void *visit(mod_expression_c *symbol); + void *visit(power_expression_c *symbol); + void *visit(neg_expression_c *symbol); + void *visit(not_expression_c *symbol); + void *visit(function_invocation_c *symbol); + + /*********************************/ + /* B 3.2.1 Assignment Statements */ + /*********************************/ + void *visit(assignment_statement_c *symbol); + + /*****************************************/ + /* B 3.2.2 Subprogram Control Statements */ + /*****************************************/ + //void *visit(fb_invocation_c *symbol); + + /********************************/ + /* B 3.2.3 Selection Statements */ + /********************************/ + void *visit(if_statement_c *symbol); + // void *visit(elseif_statement_list_c *symbol); + void *visit(elseif_statement_c *symbol); + void *visit(case_statement_c *symbol); + + /********************************/ + /* B 3.2.4 Iteration Statements */ + /********************************/ + void *visit(for_statement_c *symbol); + void *visit(while_statement_c *symbol); + void *visit(repeat_statement_c *symbol); + +}; // fill_candidate_datatypes_c + + + + + + + + + + + diff -r 0c2ef191b22a -r d48f53715f77 stage3/narrow_candidate_datatypes.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stage3/narrow_candidate_datatypes.cc Wed Feb 01 19:49:11 2012 +0000 @@ -0,0 +1,1194 @@ +/* + * matiec - a compiler for the programming languages defined in IEC 61131-3 + * + * Copyright (C) 2009-2012 Mario de Sousa (msousa@fe.up.pt) + * Copyright (C) 2012 Manuele Conti (manuele.conti@sirius-es.it) + * Copyright (C) 2012 Matteo Facchinetti (matteo.facchinetti@sirius-es.it) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * This code is made available on the understanding that it will not be + * used in safety-critical situations without a full and competent review. + */ + +/* + * An IEC 61131-3 compiler. + * + * Based on the + * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10) + * + */ + + +/* + * Narrow class select and store a data type from candidate data types list for all symbols + */ + +#include "narrow_candidate_datatypes.hh" +#include "datatype_functions.hh" +#include +#include +#include +#include +#include + + +/* set to 1 to see debug info during execution */ +static int debug = 0; + +narrow_candidate_datatypes_c::narrow_candidate_datatypes_c(symbol_c *ignore) { +} + +narrow_candidate_datatypes_c::~narrow_candidate_datatypes_c(void) { +} + +bool narrow_candidate_datatypes_c::is_widening_compatible(symbol_c *left_type, symbol_c *right_type, symbol_c *result_type, const struct widen_entry widen_table[]) { + for (int k = 0; NULL != widen_table[k].left; k++) { + if ((typeid(*left_type) == typeid(*widen_table[k].left)) + && (typeid(*right_type) == typeid(*widen_table[k].right)) + && (typeid(*result_type) == typeid(*widen_table[k].result))) { + return true; + } + } + return false; +} + +void narrow_candidate_datatypes_c::narrow_nonformal_call(symbol_c *f_call, symbol_c *f_decl) { + symbol_c *call_param_value, *param_type; + identifier_c *param_name; + function_param_iterator_c fp_iterator(f_decl); + function_call_param_iterator_c fcp_iterator(f_call); + int extensible_parameter_highest_index = -1; + identifier_c *extensible_parameter_name; + unsigned int i; + + + /* Iterating through the non-formal parameters of the function call */ + while((call_param_value = fcp_iterator.next_nf()) != NULL) { + /* Obtaining the type of the value being passed in the function call */ + /* Iterate to the next parameter of the function being called. + * Get the name of that parameter, and ignore if EN or ENO. + */ + do { + param_name = fp_iterator.next(); + /* If there is no other parameter declared, then we are passing too many parameters... */ + if(param_name == NULL) { + return; + } + } while ((strcmp(param_name->value, "EN") == 0) || (strcmp(param_name->value, "ENO") == 0)); + + /* Get the parameter type */ + call_param_value->datatype = base_type(fp_iterator.param_type()); + call_param_value->accept(*this); + if (extensible_parameter_highest_index < fp_iterator.extensible_param_index()) { + extensible_parameter_highest_index = fp_iterator.extensible_param_index(); + extensible_parameter_name = param_name; + } + } + int extensible_param_count = -1; + if (extensible_parameter_highest_index >=0) /* if call to extensible function */ + extensible_param_count = 1 + extensible_parameter_highest_index - fp_iterator.first_extensible_param_index(); + function_invocation_c *function_invocation = dynamic_cast(f_call); + if (function_invocation != NULL) function_invocation->extensible_param_count = extensible_param_count; + +} + +void narrow_candidate_datatypes_c::narrow_formal_call(symbol_c *f_call, symbol_c *f_decl) { + symbol_c *call_param_value, *call_param_name, *param_type; + symbol_c *verify_duplicate_param; + identifier_c *param_name; + function_param_iterator_c fp_iterator(f_decl); + function_call_param_iterator_c fcp_iterator(f_call); + int extensible_parameter_highest_index = -1; + identifier_c *extensible_parameter_name; + unsigned int i; + + + /* Iterating through the formal parameters of the function call */ + while((call_param_name = fcp_iterator.next_f()) != NULL) { + + /* Obtaining the value being passed in the function call */ + call_param_value = fcp_iterator.get_current_value(); + /* the following should never occur. If it does, then we have a bug in our code... */ + if (NULL == call_param_value) ERROR; + + /* Find the corresponding parameter in function declaration */ + param_name = fp_iterator.search(call_param_name); + + /* Get the parameter type */ + call_param_name->datatype = base_type(fp_iterator.param_type()); + call_param_name->accept(*this); + /* the first parameter (il_def_variable) is correct */ + if (extensible_parameter_highest_index < fp_iterator.extensible_param_index()) { + extensible_parameter_highest_index = fp_iterator.extensible_param_index(); + } + } + /* The function call may not have any errors! */ + /* In the case of a call to an extensible function, we store the highest index + * of the extensible parameters this particular call uses, in the symbol_c object + * of the function call itself! + * In calls to non-extensible functions, this value will be set to -1. + * This information is later used in stage4 to correctly generate the + * output code. + */ + int extensible_param_count = -1; + if (extensible_parameter_highest_index >=0) /* if call to extensible function */ + extensible_param_count = 1 + extensible_parameter_highest_index - fp_iterator.first_extensible_param_index(); + function_invocation_c *function_invocation = dynamic_cast(f_call); + if (function_invocation != NULL) function_invocation->extensible_param_count = extensible_param_count; +} + +/* a helper function... */ +symbol_c *narrow_candidate_datatypes_c::base_type(symbol_c *symbol) { + /* NOTE: symbol == NULL is valid. It will occur when, for e.g., an undefined/undeclared symbolic_variable is used + * in the code. + */ + return NULL; +} + +/*********************/ +/* B 1.2 - Constants */ +/*********************/ + +/**********************/ +/* B 1.3 - Data types */ +/**********************/ +/********************************/ +/* B 1.3.3 - Derived data types */ +/********************************/ +/* signed_integer DOTDOT signed_integer */ +// SYM_REF2(subrange_c, lower_limit, upper_limit) +void *narrow_candidate_datatypes_c::visit(subrange_c *symbol) { + symbol->lower_limit->datatype = symbol->datatype; + symbol->lower_limit->accept(*this); + symbol->upper_limit->datatype = symbol->datatype; + symbol->upper_limit->accept(*this); + return NULL; +} + + +/*********************/ +/* B 1.4 - Variables */ +/*********************/ + +/********************************************/ +/* B 1.4.1 - Directly Represented Variables */ +/********************************************/ + +/*************************************/ +/* B 1.4.2 - Multi-element variables */ +/*************************************/ +/* subscripted_variable '[' subscript_list ']' */ +// SYM_REF2(array_variable_c, subscripted_variable, subscript_list) +void *narrow_candidate_datatypes_c::visit(array_variable_c *symbol) { + /* we need to check the data types of the expressions used for the subscripts... */ + symbol->subscript_list->accept(*this); + return NULL; +} + + +/* subscript_list ',' subscript */ +// SYM_LIST(subscript_list_c) +void *narrow_candidate_datatypes_c::visit(subscript_list_c *symbol) { + for (int i = 0; i < symbol->n; i++) { + for (unsigned int k = 0; k < symbol->elements[i]->candidate_datatypes.size(); k++) { + if (is_ANY_INT_type(symbol->elements[i]->candidate_datatypes[k])) + symbol->elements[i]->datatype = symbol->elements[i]->candidate_datatypes[k]; + } + symbol->elements[i]->accept(*this); + } + return NULL; +} + + + +/************************************/ +/* B 1.5 Program organization units */ +/************************************/ +/*********************/ +/* B 1.5.1 Functions */ +/*********************/ +void *narrow_candidate_datatypes_c::visit(function_declaration_c *symbol) { + search_varfb_instance_type = new search_varfb_instance_type_c(symbol); + if (debug) printf("Narrowing candidate data types list in body of function %s\n", ((token_c *)(symbol->derived_function_name))->value); + prev_il_instruction = NULL; + symbol->function_body->accept(*this); + prev_il_instruction = NULL; + delete search_varfb_instance_type; + search_varfb_instance_type = NULL; + return NULL; +} + +/***************************/ +/* B 1.5.2 Function blocks */ +/***************************/ +void *narrow_candidate_datatypes_c::visit(function_block_declaration_c *symbol) { + search_varfb_instance_type = new search_varfb_instance_type_c(symbol); + if (debug) printf("Narrowing candidate data types list in body of FB %s\n", ((token_c *)(symbol->fblock_name))->value); + prev_il_instruction = NULL; + symbol->fblock_body->accept(*this); + prev_il_instruction = NULL; + delete search_varfb_instance_type; + search_varfb_instance_type = NULL; + return NULL; +} + +/********************/ +/* B 1.5.3 Programs */ +/********************/ +void *narrow_candidate_datatypes_c::visit(program_declaration_c *symbol) { + search_varfb_instance_type = new search_varfb_instance_type_c(symbol); + if (debug) printf("Narrowing candidate data types list in body of program %s\n", ((token_c *)(symbol->program_type_name))->value); + prev_il_instruction = NULL; + symbol->function_block_body->accept(*this); + prev_il_instruction = NULL; + delete search_varfb_instance_type; + search_varfb_instance_type = NULL; + return NULL; +} + + +/********************************/ +/* B 1.7 Configuration elements */ +/********************************/ +void *narrow_candidate_datatypes_c::visit(configuration_declaration_c *symbol) { +#if 0 + // TODO !!! + /* for the moment we must return NULL so semantic analysis of remaining code is not interrupted! */ +#endif + return NULL; +} + + +/****************************************/ +/* B.2 - Language IL (Instruction List) */ +/****************************************/ +/***********************************/ +/* B 2.1 Instructions and Operands */ +/***********************************/ +// void *visit(instruction_list_c *symbol); +void *narrow_candidate_datatypes_c::visit(il_simple_operation_c *symbol) { + il_operand = symbol->il_operand; + if (NULL != symbol->il_operand) { + symbol->il_operand->accept(*this); + } + /* recursive call to see whether data types are compatible */ + symbol->il_simple_operator->accept(*this); + il_operand = NULL; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(il_function_call_c *symbol) { + return NULL; +} + +/* MJS: Manuele, could you please not delete the following 2 lines of comments. They help me understand where this class is used + * and when it is created by bison - syntax parse, and how it can show up in the abstract syntax tree. + * + * Actually, it could be helpful if we could have all the similar comments already present in visit_expression_type_c + * in the 3 new classes fill/narrow/print candidate datatype + */ +/* | il_expr_operator '(' [il_operand] eol_list [simple_instr_list] ')' */ +// SYM_REF3(il_expression_c, il_expr_operator, il_operand, simple_instr_list); +void *narrow_candidate_datatypes_c::visit(il_expression_c *symbol) { +/* MJS: TODO... */ +return NULL; +} + +void *narrow_candidate_datatypes_c::visit(il_fb_call_c *symbol) { + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(il_formal_funct_call_c *symbol) { + return NULL; +} + + +/* + void *visit(il_operand_list_c *symbol); + void *visit(simple_instr_list_c *symbol); + void *visit(il_param_list_c *symbol); + void *visit(il_param_assignment_c *symbol); + void *visit(il_param_out_assignment_c *symbol); + */ + +/*******************/ +/* B 2.2 Operators */ +/*******************/ +void *narrow_candidate_datatypes_c::visit(LD_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(LDN_operator_c *symbol) { + if (symbol->candidate_datatypes.size() != 1) + return NULL; + symbol->datatype = symbol->candidate_datatypes[0]; + il_operand->datatype = symbol->datatype; + il_operand->accept(*this); + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(ST_operator_c *symbol) { + if (symbol->candidate_datatypes.size() != 1) + return NULL; + symbol->datatype = symbol->candidate_datatypes[0]; + il_operand->datatype = symbol->datatype; + il_operand->accept(*this); + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(STN_operator_c *symbol) { + if (symbol->candidate_datatypes.size() != 1) + return NULL; + symbol->datatype = symbol->candidate_datatypes[0]; + il_operand->datatype = symbol->datatype; + il_operand->accept(*this); + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(NOT_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(S_operator_c *symbol) { + if (symbol->candidate_datatypes.size() != 1) + return NULL; + symbol->datatype = symbol->candidate_datatypes[0]; + il_operand->datatype = symbol->datatype; + il_operand->accept(*this); + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(R_operator_c *symbol) { + if (symbol->candidate_datatypes.size() != 1) + return NULL; + symbol->datatype = symbol->candidate_datatypes[0]; + il_operand->datatype = symbol->datatype; + il_operand->accept(*this); + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(S1_operator_c *symbol) { + if (symbol->candidate_datatypes.size() != 1) + return NULL; + symbol->datatype = symbol->candidate_datatypes[0]; + il_operand->datatype = symbol->datatype; + il_operand->accept(*this); + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(R1_operator_c *symbol) { + if (symbol->candidate_datatypes.size() != 1) + return NULL; + symbol->datatype = symbol->candidate_datatypes[0]; + il_operand->datatype = symbol->datatype; + il_operand->accept(*this); + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(CLK_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(CU_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(CD_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(PV_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(IN_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(PT_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(AND_operator_c *symbol) { + if (symbol->candidate_datatypes.size() != 1) + return NULL; + symbol->datatype = symbol->candidate_datatypes[0]; + il_operand->datatype = symbol->datatype; + il_operand->accept(*this); + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(OR_operator_c *symbol) { + if (symbol->candidate_datatypes.size() != 1) + return NULL; + symbol->datatype = symbol->candidate_datatypes[0]; + il_operand->datatype = symbol->datatype; + il_operand->accept(*this); + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(XOR_operator_c *symbol) { + if (symbol->candidate_datatypes.size() != 1) + return NULL; + symbol->datatype = symbol->candidate_datatypes[0]; + il_operand->datatype = symbol->datatype; + il_operand->accept(*this); + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(ANDN_operator_c *symbol) { + if (symbol->candidate_datatypes.size() != 1) + return NULL; + symbol->datatype = symbol->candidate_datatypes[0]; + il_operand->datatype = symbol->datatype; + il_operand->accept(*this); + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(ORN_operator_c *symbol) { + if (symbol->candidate_datatypes.size() != 1) + return NULL; + symbol->datatype = symbol->candidate_datatypes[0]; + il_operand->datatype = symbol->datatype; + il_operand->accept(*this); + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(XORN_operator_c *symbol) { + if (symbol->candidate_datatypes.size() != 1) + return NULL; + symbol->datatype = symbol->candidate_datatypes[0]; + il_operand->datatype = symbol->datatype; + il_operand->accept(*this); + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(ADD_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(SUB_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(MUL_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(DIV_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(MOD_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(GT_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(GE_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(EQ_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(LT_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(LE_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(NE_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(CAL_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(CALC_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(CALCN_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(RET_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(RETC_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(RETCN_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(JMP_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(JMPC_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(JMPCN_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +/* Symbol class handled together with function call checks */ +// void *visit(il_assign_operator_c *symbol, variable_name); +/* Symbol class handled together with function call checks */ +// void *visit(il_assign_operator_c *symbol, option, variable_name); + + +/***************************************/ +/* B.3 - Language ST (Structured Text) */ +/***************************************/ +/***********************/ +/* B 3.1 - Expressions */ +/***********************/ + +void *narrow_candidate_datatypes_c::visit(or_expression_c *symbol) { + symbol_c * selected_type = NULL; + for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) { + if (is_type_equal(symbol->l_exp->candidate_datatypes[i], symbol->r_exp->candidate_datatypes[j])) { + selected_type = symbol->l_exp->candidate_datatypes[i]; + break; + } + } + } + + if (NULL != selected_type) { + symbol->l_exp->datatype = selected_type; + symbol->l_exp->accept(*this); + symbol->r_exp->datatype = selected_type; + symbol->r_exp->accept(*this); + } + else + ERROR; + return NULL; +} + + +void *narrow_candidate_datatypes_c::visit(xor_expression_c *symbol) { + symbol_c * selected_type = NULL; + for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) { + if (is_type_equal(symbol->l_exp->candidate_datatypes[i], symbol->r_exp->candidate_datatypes[j])) { + selected_type = symbol->l_exp->candidate_datatypes[i]; + break; + } + } + } + + if (NULL != selected_type) { + symbol->l_exp->datatype = selected_type; + symbol->l_exp->accept(*this); + symbol->r_exp->datatype = selected_type; + symbol->r_exp->accept(*this); + } + else + ERROR; + return NULL; +} + + +void *narrow_candidate_datatypes_c::visit(and_expression_c *symbol) { + symbol_c * selected_type = NULL; + for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) { + if (typeid(*symbol->l_exp->candidate_datatypes[i]) == typeid(*symbol->r_exp->candidate_datatypes[j])) { + selected_type = symbol->l_exp->candidate_datatypes[i]; + break; + } + } + } + + if (NULL != selected_type) { + symbol->l_exp->datatype = selected_type; + symbol->l_exp->accept(*this); + symbol->r_exp->datatype = selected_type; + symbol->r_exp->accept(*this); + } + else + ERROR; + return NULL; +} + + +void *narrow_candidate_datatypes_c::visit(equ_expression_c *symbol) { + /* Here symbol->datatype has already assigned to BOOL + * In conditional symbols like =, <>, =<, <, >, >= we have to set + * l_exp and r_exp expression matched with compatible type. + * Example: + * INT#14 = INT#81 + * equ_expression_c symbol->datatype = BOOL from top visit + * symbol->l_exp->datatype => INT + * symbol->r_exp->datatype => INT + */ + symbol_c * selected_type = NULL; + for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) { + if (typeid(*symbol->l_exp->candidate_datatypes[i]) == typeid(*symbol->r_exp->candidate_datatypes[j])) { + /* + * We do not need to check whether the type is an ANY_ELEMENTARY here. + * That was already done in fill_candidate_datatypes_c. + */ + selected_type = symbol->l_exp->candidate_datatypes[i]; + break; + } + } + } + + if (NULL != selected_type) { + symbol->l_exp->datatype = selected_type; + symbol->l_exp->accept(*this); + symbol->r_exp->datatype = selected_type; + symbol->r_exp->accept(*this); + } + else + ERROR; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(notequ_expression_c *symbol) { + symbol_c * selected_type = NULL; + for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) { + if (typeid(*symbol->l_exp->candidate_datatypes[i]) == typeid(*symbol->r_exp->candidate_datatypes[j])) { + selected_type = symbol->l_exp->candidate_datatypes[i]; + break; + } + } + } + + if (NULL != selected_type) { + symbol->l_exp->datatype = selected_type; + symbol->l_exp->accept(*this); + symbol->r_exp->datatype = selected_type; + symbol->r_exp->accept(*this); + } + else + ERROR; + return NULL; +} + + +void *narrow_candidate_datatypes_c::visit(lt_expression_c *symbol) { + symbol_c * selected_type = NULL; + for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) { + if (typeid(*symbol->l_exp->candidate_datatypes[i]) == typeid(*symbol->r_exp->candidate_datatypes[j]) + && is_ANY_ELEMENTARY_type(symbol->l_exp->candidate_datatypes[i])) { + selected_type = symbol->l_exp->candidate_datatypes[i]; + break; + } + } + } + + if (NULL != selected_type) { + symbol->l_exp->datatype = selected_type; + symbol->l_exp->accept(*this); + symbol->r_exp->datatype = selected_type; + symbol->r_exp->accept(*this); + } + else + ERROR; + return NULL; +} + + +void *narrow_candidate_datatypes_c::visit(gt_expression_c *symbol) { + symbol_c * selected_type = NULL; + for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) { + if (typeid(*symbol->l_exp->candidate_datatypes[i]) == typeid(*symbol->r_exp->candidate_datatypes[j]) + && is_ANY_ELEMENTARY_type(symbol->l_exp->candidate_datatypes[i])) { + selected_type = symbol->l_exp->candidate_datatypes[i]; + break; + } + } + } + + if (NULL != selected_type) { + symbol->l_exp->datatype = selected_type; + symbol->l_exp->accept(*this); + symbol->r_exp->datatype = selected_type; + symbol->r_exp->accept(*this); + } + else + ERROR; + return NULL; +} + + +void *narrow_candidate_datatypes_c::visit(le_expression_c *symbol) { + symbol_c * selected_type = NULL; + for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) { + if (typeid(*symbol->l_exp->candidate_datatypes[i]) == typeid(*symbol->r_exp->candidate_datatypes[j]) + && is_ANY_ELEMENTARY_type(symbol->l_exp->candidate_datatypes[i])) { + selected_type = symbol->l_exp->candidate_datatypes[i]; + break; + } + } + } + + if (NULL != selected_type) { + symbol->l_exp->datatype = selected_type; + symbol->l_exp->accept(*this); + symbol->r_exp->datatype = selected_type; + symbol->r_exp->accept(*this); + } + else + ERROR; + return NULL; +} + + +void *narrow_candidate_datatypes_c::visit(ge_expression_c *symbol) { + symbol_c * selected_type = NULL; + for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) { + if (typeid(*symbol->l_exp->candidate_datatypes[i]) == typeid(*symbol->r_exp->candidate_datatypes[j]) + && is_ANY_ELEMENTARY_type(symbol->l_exp->candidate_datatypes[i])) { + selected_type = symbol->l_exp->candidate_datatypes[i]; + break; + } + } + } + + if (NULL != selected_type) { + symbol->l_exp->datatype = selected_type; + symbol->l_exp->accept(*this); + symbol->r_exp->datatype = selected_type; + symbol->r_exp->accept(*this); + } + else + ERROR; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(add_expression_c *symbol) { + int count = 0; + + if (is_ANY_NUM_compatible(symbol->datatype)) { + symbol->l_exp->datatype = symbol->datatype; + symbol->r_exp->datatype = symbol->datatype; + count++; + } else { + /* TIME data type */ + for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) { + /* test widening compatibility */ + if (is_widening_compatible(symbol->l_exp->candidate_datatypes[i], + symbol->r_exp->candidate_datatypes[j], + symbol->datatype, widen_ADD_table)) { + symbol->l_exp->datatype = symbol->l_exp->candidate_datatypes[i]; + symbol->r_exp->datatype = symbol->r_exp->candidate_datatypes[j]; + count ++; + } + } + } + } + if (count > 1) + ERROR; + symbol->l_exp->accept(*this); + symbol->r_exp->accept(*this); + return NULL; +} + + + +void *narrow_candidate_datatypes_c::visit(sub_expression_c *symbol) { + int count = 0; + + if (is_ANY_NUM_compatible(symbol->datatype)) { + symbol->l_exp->datatype = symbol->datatype; + symbol->r_exp->datatype = symbol->datatype; + count++; + } else { + /* TIME data type */ + for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) { + /* test widening compatibility */ + if (is_widening_compatible(symbol->l_exp->candidate_datatypes[i], + symbol->r_exp->candidate_datatypes[j], + symbol->datatype, widen_SUB_table)) { + symbol->l_exp->datatype = symbol->l_exp->candidate_datatypes[i]; + symbol->r_exp->datatype = symbol->r_exp->candidate_datatypes[j]; + count ++; + } + } + } + } + if (count > 1) + ERROR; + symbol->l_exp->accept(*this); + symbol->r_exp->accept(*this); + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(mul_expression_c *symbol) { + int count = 0; + + if (is_ANY_NUM_compatible(symbol->datatype)) { + symbol->l_exp->datatype = symbol->datatype; + symbol->r_exp->datatype = symbol->datatype; + count++; + } else { + /* TIME data type */ + for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) { + /* test widening compatibility */ + if (is_widening_compatible(symbol->l_exp->candidate_datatypes[i], + symbol->r_exp->candidate_datatypes[j], + symbol->datatype, widen_MUL_table)) { + symbol->l_exp->datatype = symbol->l_exp->candidate_datatypes[i]; + symbol->r_exp->datatype = symbol->r_exp->candidate_datatypes[j]; + count ++; + } + } + } + } + if (count > 1) + ERROR; + symbol->l_exp->accept(*this); + symbol->r_exp->accept(*this); + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(div_expression_c *symbol) { + int count = 0; + + if (is_ANY_NUM_compatible(symbol->datatype)) { + symbol->l_exp->datatype = symbol->datatype; + symbol->r_exp->datatype = symbol->datatype; + count++; + } else { + /* TIME data type */ + for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) { + for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) { + /* test widening compatibility */ + if (is_widening_compatible(symbol->l_exp->candidate_datatypes[i], + symbol->r_exp->candidate_datatypes[j], + symbol->datatype, widen_DIV_table)) { + symbol->l_exp->datatype = symbol->l_exp->candidate_datatypes[i]; + symbol->r_exp->datatype = symbol->r_exp->candidate_datatypes[j]; + count ++; + } + } + } + } + if (count > 1) + ERROR; + symbol->l_exp->accept(*this); + symbol->r_exp->accept(*this); + return NULL; +} + + +void *narrow_candidate_datatypes_c::visit(mod_expression_c *symbol) { + symbol->l_exp->datatype = symbol->datatype; + symbol->l_exp->accept(*this); + symbol->r_exp->datatype = symbol->datatype; + symbol->r_exp->accept(*this); + return NULL; +} + + +void *narrow_candidate_datatypes_c::visit(power_expression_c *symbol) { + symbol->l_exp->datatype = symbol->datatype; + symbol->l_exp->accept(*this); + if (! symbol->r_exp->candidate_datatypes.size()){ + symbol->r_exp->datatype = symbol->r_exp->candidate_datatypes[0]; + symbol->r_exp->accept(*this); + } + return NULL; +} + + +void *narrow_candidate_datatypes_c::visit(neg_expression_c *symbol) { + symbol->exp->datatype = symbol->datatype; + symbol->exp->accept(*this); + return NULL; +} + + +void *narrow_candidate_datatypes_c::visit(not_expression_c *symbol) { + symbol->exp->datatype = symbol->datatype; + symbol->exp->accept(*this); + return NULL; +} + + +void *narrow_candidate_datatypes_c::visit(function_invocation_c *symbol) { + function_declaration_c *f_decl; + list_c *parameter_list; + list_c *parameter_candidate_datatypes; + function_symtable_t::iterator lower = function_symtable.lower_bound(symbol->function_name); + function_symtable_t::iterator upper = function_symtable.upper_bound(symbol->function_name); + + if (NULL != symbol->formal_param_list) + parameter_list = (list_c *)symbol->formal_param_list; + else if (NULL != symbol->nonformal_param_list) + parameter_list = (list_c *)symbol->nonformal_param_list; + else ERROR; + for(; lower != upper; lower++) { + f_decl = function_symtable.get_value(lower); + symbol_c * return_type = base_type(f_decl->type_name); + if (return_type && typeid(*symbol->datatype) != typeid(*return_type)) + continue; + /* We set which function declaration it'll use in STAGE4 */ + symbol->called_function_declaration = f_decl; + /* Check if function declaration in symbol_table is compatible with parameters */ + if (NULL != symbol->nonformal_param_list) + /* nonformal parameter function call */ + narrow_nonformal_call(symbol, f_decl); + else + /* formal parameter function call */ + narrow_formal_call (symbol, f_decl); + break; + } + + return NULL; +} + +/********************/ +/* B 3.2 Statements */ +/********************/ + + +/*********************************/ +/* B 3.2.1 Assignment Statements */ +/*********************************/ + +void *narrow_candidate_datatypes_c::visit(assignment_statement_c *symbol) { + if (symbol->candidate_datatypes.size() != 1) + return NULL; + symbol->datatype = symbol->candidate_datatypes[0]; + symbol->l_exp->datatype = symbol->datatype; + symbol->l_exp->accept(*this); + symbol->r_exp->datatype = symbol->datatype; + symbol->r_exp->accept(*this); + return NULL; +} + + +/*****************************************/ +/* B 3.2.2 Subprogram Control Statements */ +/*****************************************/ + +/********************************/ +/* B 3.2.3 Selection Statements */ +/********************************/ + +void *narrow_candidate_datatypes_c::visit(if_statement_c *symbol) { + for(unsigned int i = 0; i < symbol->expression->candidate_datatypes.size(); i++) { + if (is_type(symbol->expression->candidate_datatypes[i], bool_type_name_c)) + symbol->expression->datatype = symbol->expression->candidate_datatypes[i]; + } + symbol->expression->accept(*this); + if (NULL != symbol->statement_list) + symbol->statement_list->accept(*this); + if (NULL != symbol->elseif_statement_list) + symbol->elseif_statement_list->accept(*this); + if (NULL != symbol->else_statement_list) + symbol->else_statement_list->accept(*this); + return NULL; +} + + +void *narrow_candidate_datatypes_c::visit(elseif_statement_c *symbol) { + for (unsigned int i = 0; i < symbol->expression->candidate_datatypes.size(); i++) { + if (is_type(symbol->expression->candidate_datatypes[i], bool_type_name_c)) + symbol->expression->datatype = symbol->expression->candidate_datatypes[i]; + } + symbol->expression->accept(*this); + if (NULL != symbol->statement_list) + symbol->statement_list->accept(*this); + return NULL; +} + +/* CASE expression OF case_element_list ELSE statement_list END_CASE */ +// SYM_REF3(case_statement_c, expression, case_element_list, statement_list) +void *narrow_candidate_datatypes_c::visit(case_statement_c *symbol) { + for (unsigned int i = 0; i < symbol->expression->candidate_datatypes.size(); i++) { + if ((is_ANY_INT_type(symbol->expression->candidate_datatypes[i])) + || (search_base_type.type_is_enumerated(symbol->expression->candidate_datatypes[i]))) + symbol->expression->datatype = symbol->expression->candidate_datatypes[i]; + } + symbol->expression->accept(*this); + if (NULL != symbol->statement_list) + symbol->statement_list->accept(*this); + if (NULL != symbol->case_element_list) { + symbol->case_element_list->datatype = symbol->expression->datatype; + symbol->case_element_list->accept(*this); + } + return NULL; +} + +/* helper symbol for case_statement */ +// SYM_LIST(case_element_list_c) +void *narrow_candidate_datatypes_c::visit(case_element_list_c *symbol) { + for (int i = 0; i < symbol->n; i++) { + symbol->elements[i]->datatype = symbol->datatype; + symbol->elements[i]->accept(*this); + } + return NULL; +} + +/* case_list ':' statement_list */ +// SYM_REF2(case_element_c, case_list, statement_list) +void *narrow_candidate_datatypes_c::visit(case_element_c *symbol) { + symbol->case_list->datatype = symbol->datatype; + symbol->case_list->accept(*this); + symbol->statement_list->accept(*this); + return NULL; +} + +// SYM_LIST(case_list_c) +void *narrow_candidate_datatypes_c::visit(case_list_c *symbol) { + for (int i = 0; i < symbol->n; i++) { + for (unsigned int k = 0; k < symbol->elements[i]->candidate_datatypes.size(); k++) { + if (is_type_equal(symbol->datatype, symbol->elements[i]->candidate_datatypes[k])) + symbol->elements[i]->datatype = symbol->elements[i]->candidate_datatypes[k]; + } + /* NOTE: this may be an integer, a subrange_c, or a enumerated value! */ + symbol->elements[i]->accept(*this); + } + return NULL; +} + + +/********************************/ +/* B 3.2.4 Iteration Statements */ +/********************************/ +void *narrow_candidate_datatypes_c::visit(for_statement_c *symbol) { + /* Control variable */ + for(unsigned int i = 0; i < symbol->control_variable->candidate_datatypes.size(); i++) { + if (is_ANY_INT_type(symbol->control_variable->candidate_datatypes[i])) { + symbol->control_variable->datatype = symbol->control_variable->candidate_datatypes[i]; + } + } + symbol->control_variable->accept(*this); + /* BEG expression */ + for(unsigned int i = 0; i < symbol->beg_expression->candidate_datatypes.size(); i++) { + if (is_type_equal(symbol->control_variable->datatype,symbol->beg_expression->candidate_datatypes[i]) && + is_ANY_INT_type(symbol->beg_expression->candidate_datatypes[i])) { + symbol->beg_expression->datatype = symbol->beg_expression->candidate_datatypes[i]; + } + } + symbol->beg_expression->accept(*this); + /* END expression */ + for(unsigned int i = 0; i < symbol->end_expression->candidate_datatypes.size(); i++) { + if (is_type_equal(symbol->control_variable->datatype,symbol->end_expression->candidate_datatypes[i]) && + is_ANY_INT_type(symbol->end_expression->candidate_datatypes[i])) { + symbol->end_expression->datatype = symbol->end_expression->candidate_datatypes[i]; + } + } + symbol->end_expression->accept(*this); + /* BY expression */ + if (NULL != symbol->by_expression) { + for(unsigned int i = 0; i < symbol->by_expression->candidate_datatypes.size(); i++) { + if (is_type_equal(symbol->control_variable->datatype,symbol->by_expression->candidate_datatypes[i]) && + is_ANY_INT_type(symbol->by_expression->candidate_datatypes[i])) { + symbol->by_expression->datatype = symbol->by_expression->candidate_datatypes[i]; + } + } + symbol->by_expression->accept(*this); + } + if (NULL != symbol->statement_list) + symbol->statement_list->accept(*this); + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(while_statement_c *symbol) { + for (unsigned int i = 0; i < symbol->expression->candidate_datatypes.size(); i++) { + if(is_BOOL_type(symbol->expression->candidate_datatypes[i])) + symbol->expression->datatype = symbol->expression->candidate_datatypes[i]; + } + symbol->expression->accept(*this); + if (NULL != symbol->statement_list) + symbol->statement_list->accept(*this); + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(repeat_statement_c *symbol) { + for (unsigned int i = 0; i < symbol->expression->candidate_datatypes.size(); i++) { + if(is_BOOL_type(symbol->expression->candidate_datatypes[i])) + symbol->expression->datatype = symbol->expression->candidate_datatypes[i]; + } + symbol->expression->accept(*this); + if (NULL != symbol->statement_list) + symbol->statement_list->accept(*this); + return NULL; +} + + + + + diff -r 0c2ef191b22a -r d48f53715f77 stage3/narrow_candidate_datatypes.hh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stage3/narrow_candidate_datatypes.hh Wed Feb 01 19:49:11 2012 +0000 @@ -0,0 +1,224 @@ +/* + * matiec - a compiler for the programming languages defined in IEC 61131-3 + * + * Copyright (C) 2009-2012 Mario de Sousa (msousa@fe.up.pt) + * Copyright (C) 2012 Manuele Conti (manuele.conti@sirius-es.it) + * Copyright (C) 2012 Matteo Facchinetti (matteo.facchinetti@sirius-es.it) + * + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * This code is made available on the understanding that it will not be + * used in safety-critical situations without a full and competent review. + */ + +/* + * An IEC 61131-3 compiler. + * + * Based on the + * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10) + * + */ + + +#include "../absyntax_utils/absyntax_utils.hh" + +class narrow_candidate_datatypes_c: public iterator_visitor_c { + + private: + symbol_c * selected_datatype; + search_varfb_instance_type_c *search_varfb_instance_type; + search_base_type_c search_base_type; + symbol_c *case_expression_type; + symbol_c *il_operand; + symbol_c *prev_il_instruction; + + bool is_widening_compatible(symbol_c *left_type, symbol_c *right_type, symbol_c *result_type, const struct widen_entry widen_table[]); + + public: + narrow_candidate_datatypes_c(symbol_c *ignore); + virtual ~narrow_candidate_datatypes_c(void); + void narrow_nonformal_call(symbol_c *f_call, symbol_c *f_decl); + void narrow_formal_call(symbol_c *f_call, symbol_c *f_decl); + + symbol_c *base_type(symbol_c *symbol); + + /**********************/ + /* B 1.3 - Data types */ + /**********************/ + /********************************/ + /* B 1.3.3 - Derived data types */ + /********************************/ + void *visit(subrange_c *symbol); + + /*********************/ + /* B 1.4 - Variables */ + /*********************/ + /********************************************/ + /* B 1.4.1 - Directly Represented Variables */ + /********************************************/ + /*************************************/ + /* B 1.4.2 - Multi-element variables */ + /*************************************/ + void *visit(array_variable_c *symbol); + void *visit(subscript_list_c *symbol); + + /**************************************/ + /* B 1.5 - Program organization units */ + /**************************************/ + /***********************/ + /* B 1.5.1 - Functions */ + /***********************/ + void *visit(function_declaration_c *symbol); + + /*****************************/ + /* B 1.5.2 - Function blocks */ + /*****************************/ + void *visit(function_block_declaration_c *symbol); + + /**********************/ + /* B 1.5.3 - Programs */ + /**********************/ + void *visit(program_declaration_c *symbol); + + /********************************/ + /* B 1.7 Configuration elements */ + /********************************/ + void *visit(configuration_declaration_c *symbol); + /****************************************/ + /* B.2 - Language IL (Instruction List) */ + /****************************************/ + /***********************************/ + /* B 2.1 Instructions and Operands */ + /***********************************/ + // void *visit(instruction_list_c *symbol); + void *visit(il_simple_operation_c *symbol); + void *visit(il_function_call_c *symbol); + void *visit(il_expression_c *symbol); + void *visit(il_fb_call_c *symbol); + void *visit(il_formal_funct_call_c *symbol); + /* + void *visit(il_operand_list_c *symbol); + void *visit(simple_instr_list_c *symbol); + void *visit(il_param_list_c *symbol); + void *visit(il_param_assignment_c *symbol); + void *visit(il_param_out_assignment_c *symbol); + */ + + /*******************/ + /* B 2.2 Operators */ + /*******************/ + void *visit(LD_operator_c *symbol); + void *visit(LDN_operator_c *symbol); + void *visit(ST_operator_c *symbol); + void *visit(STN_operator_c *symbol); + void *visit(NOT_operator_c *symbol); + void *visit(S_operator_c *symbol); + void *visit(R_operator_c *symbol); + void *visit(S1_operator_c *symbol); + void *visit(R1_operator_c *symbol); + void *visit(CLK_operator_c *symbol); + void *visit(CU_operator_c *symbol); + void *visit(CD_operator_c *symbol); + void *visit(PV_operator_c *symbol); + void *visit(IN_operator_c *symbol); + void *visit(PT_operator_c *symbol); + void *visit(AND_operator_c *symbol); + void *visit(OR_operator_c *symbol); + void *visit(XOR_operator_c *symbol); + void *visit(ANDN_operator_c *symbol); + void *visit(ORN_operator_c *symbol); + void *visit(XORN_operator_c *symbol); + void *visit(ADD_operator_c *symbol); + void *visit(SUB_operator_c *symbol); + void *visit(MUL_operator_c *symbol); + void *visit(DIV_operator_c *symbol); + void *visit(MOD_operator_c *symbol); + void *visit(GT_operator_c *symbol); + void *visit(GE_operator_c *symbol); + void *visit(EQ_operator_c *symbol); + void *visit(LT_operator_c *symbol); + void *visit(LE_operator_c *symbol); + void *visit(NE_operator_c *symbol); + void *visit(CAL_operator_c *symbol); + void *visit(CALC_operator_c *symbol); + void *visit(CALCN_operator_c *symbol); + void *visit(RET_operator_c *symbol); + void *visit(RETC_operator_c *symbol); + void *visit(RETCN_operator_c *symbol); + void *visit(JMP_operator_c *symbol); + void *visit(JMPC_operator_c *symbol); + void *visit(JMPCN_operator_c *symbol); + /* Symbol class handled together with function call checks */ + // void *visit(il_assign_operator_c *symbol, variable_name); + /* Symbol class handled together with function call checks */ + // void *visit(il_assign_operator_c *symbol, option, variable_name); + /***************************************/ + /* B.3 - Language ST (Structured Text) */ + /***************************************/ + /***********************/ + /* B 3.1 - Expressions */ + /***********************/ + void *visit(or_expression_c *symbol); + void *visit(xor_expression_c *symbol); + void *visit(and_expression_c *symbol); + void *visit(equ_expression_c *symbol); + void *visit(notequ_expression_c *symbol); + void *visit(lt_expression_c *symbol); + void *visit(gt_expression_c *symbol); + void *visit(le_expression_c *symbol); + void *visit(ge_expression_c *symbol); + void *visit(add_expression_c *symbol); + void *visit(sub_expression_c *symbol); + void *visit(mul_expression_c *symbol); + void *visit(div_expression_c *symbol); + void *visit(mod_expression_c *symbol); + void *visit(power_expression_c *symbol); + void *visit(neg_expression_c *symbol); + void *visit(not_expression_c *symbol); + + void *visit(function_invocation_c *symbol); + + /*********************************/ + /* B 3.2.1 Assignment Statements */ + /*********************************/ + void *visit(assignment_statement_c *symbol); + + /********************************/ + /* B 3.2.3 Selection Statements */ + /********************************/ + void *visit(if_statement_c *symbol); + void *visit(elseif_statement_c *symbol); + void *visit(case_statement_c *symbol); + void *visit(case_element_list_c *symbol); + void *visit(case_element_c *symbol); + void *visit(case_list_c *symbol); + + /********************************/ + /* B 3.2.4 Iteration Statements */ + /********************************/ + void *visit(for_statement_c *symbol); + void *visit(while_statement_c *symbol); + void *visit(repeat_statement_c *symbol); + +}; // narrow_candidate_datatypes_c + + + + + + + + diff -r 0c2ef191b22a -r d48f53715f77 stage3/print_datatypes_error.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stage3/print_datatypes_error.cc Wed Feb 01 19:49:11 2012 +0000 @@ -0,0 +1,1162 @@ +/* + * matiec - a compiler for the programming languages defined in IEC 61131-3 + * + * Copyright (C) 2009-2011 Mario de Sousa (msousa@fe.up.pt) + * Copyright (C) 20011-2012 Manuele Conti (manuele.conti@sirius-es.it) + * Copyright (C) 20011-2012 Matteo Facchinetti (matteo.facchinetti@sirius-es.it) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * This code is made available on the understanding that it will not be + * used in safety-critical situations without a full and competent review. + */ + +/* + * An IEC 61131-3 compiler. + * + * Based on the + * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10) + * + */ + + +/* + * Fill candidate list of data types for all symbols + */ + +#include "print_datatypes_error.hh" +#include +#include +#include +#include +#include + + +#define FIRST_(symbol1, symbol2) (((symbol1)->first_order < (symbol2)->first_order) ? (symbol1) : (symbol2)) +#define LAST_(symbol1, symbol2) (((symbol1)->last_order > (symbol2)->last_order) ? (symbol1) : (symbol2)) + +#define STAGE3_ERROR(symbol1, symbol2, ...) { \ + fprintf(stderr, "%s:%d-%d..%d-%d: error : ", \ + FIRST_(symbol1,symbol2)->first_file, FIRST_(symbol1,symbol2)->first_line, FIRST_(symbol1,symbol2)->first_column, \ + LAST_(symbol1,symbol2) ->last_line, LAST_(symbol1,symbol2) ->last_column); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n"); \ + il_error = true; \ + error_found = true;\ + } + + +/* set to 1 to see debug info during execution */ +static int debug = 0; + +print_datatypes_error_c::print_datatypes_error_c(symbol_c *ignore) { + error_found = false; +} + +print_datatypes_error_c::~print_datatypes_error_c(void) { + error_found = false; +} + +int print_datatypes_error_c::get_error_found() { + return error_found; +} + +/* a helper function... */ +symbol_c *print_datatypes_error_c::base_type(symbol_c *symbol) { + /* NOTE: symbol == NULL is valid. It will occur when, for e.g., an undefined/undeclared symbolic_variable is used + * in the code. + */ + if (symbol == NULL) return NULL; + return (symbol_c *)symbol->accept(search_base_type); +} + +/*********************/ +/* B 1.2 - Constants */ +/*********************/ +/******************************/ +/* B 1.2.1 - Numeric Literals */ +/******************************/ +void *print_datatypes_error_c::visit(real_c *symbol) { + if (symbol->candidate_datatypes.size() == 0) { + STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_REAL data type."); + } else if (NULL == symbol->datatype) { + STAGE3_ERROR(symbol, symbol, "ANY_REAL data type not valid in this location."); + } + return NULL; +} + +void *print_datatypes_error_c::visit(integer_c *symbol) { + if (symbol->candidate_datatypes.size() == 0) { + STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_INT data type."); + } else if (NULL == symbol->datatype) { + STAGE3_ERROR(symbol, symbol, "ANY_INT data type not valid in this location."); + } + return NULL; +} + +void *print_datatypes_error_c::visit(neg_real_c *symbol) { + if (symbol->candidate_datatypes.size() == 0) { + STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_REAL data type."); + } else if (NULL == symbol->datatype) { + STAGE3_ERROR(symbol, symbol, "ANY_REAL data type not valid in this location."); + } + return NULL; +} + +void *print_datatypes_error_c::visit(neg_integer_c *symbol) { + if (symbol->candidate_datatypes.size() == 0) { + STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_INT data type."); + } else if (NULL == symbol->datatype) { + STAGE3_ERROR(symbol, symbol, "ANY_INT data type not valid in this location."); + } + return NULL; +} + +void *print_datatypes_error_c::visit(binary_integer_c *symbol) { + if (symbol->candidate_datatypes.size() == 0) { + STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_INT data type."); + } else if (NULL == symbol->datatype) { + STAGE3_ERROR(symbol, symbol, "ANY_INT data type not valid in this location."); + } + return NULL; +} + +void *print_datatypes_error_c::visit(octal_integer_c *symbol) { + if (symbol->candidate_datatypes.size() == 0) { + STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_INT data type."); + } else if (NULL == symbol->datatype) { + STAGE3_ERROR(symbol, symbol, "ANY_INT data type not valid in this location."); + } + return NULL; +} + +void *print_datatypes_error_c::visit(hex_integer_c *symbol) { + if (symbol->candidate_datatypes.size() == 0) { + STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_INT data type."); + } else if (NULL == symbol->datatype) { + STAGE3_ERROR(symbol, symbol, "ANY_INT data type not valid in this location."); + } + return NULL; +} + +void *print_datatypes_error_c::visit(integer_literal_c *symbol) { + if (symbol->candidate_datatypes.size() == 0) { + STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_INT data type."); + } else if (NULL == symbol->datatype) { + STAGE3_ERROR(symbol, symbol, "ANY_INT data type not valid in this location."); + } + return NULL; +} + +void *print_datatypes_error_c::visit(real_literal_c *symbol) { + if (symbol->candidate_datatypes.size() == 0) { + STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_REAL data type."); + } else if (NULL == symbol->datatype) { + STAGE3_ERROR(symbol, symbol, "ANY_REAL data type not valid in this location."); + } + return NULL; +} + +void *print_datatypes_error_c::visit(bit_string_literal_c *symbol) { + if (symbol->candidate_datatypes.size() == 0) { + STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_BIT data type."); + } else if (NULL == symbol->datatype) { + STAGE3_ERROR(symbol, symbol, "ANY_BIT data type not valid in this location."); + } + return NULL; +} + +void *print_datatypes_error_c::visit(boolean_literal_c *symbol) { + if (symbol->candidate_datatypes.size() == 0) { + STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_BOOL data type."); + } else if (NULL == symbol->datatype) { + STAGE3_ERROR(symbol, symbol, "ANY_BOOL data type not valid in this location."); + } + return NULL; +} + +void *print_datatypes_error_c::visit(boolean_true_c *symbol) { + if (symbol->candidate_datatypes.size() == 0) { + STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_BOOL data type."); + } else if (NULL == symbol->datatype) { + STAGE3_ERROR(symbol, symbol, "ANY_BOOL data type not valid in this location."); + } + return NULL; +} + +void *print_datatypes_error_c::visit(boolean_false_c *symbol) { + if (symbol->candidate_datatypes.size() == 0) { + STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_BOOL data type."); + } else if (NULL == symbol->datatype) { + STAGE3_ERROR(symbol, symbol, "ANY_BOOL data type not valid in this location."); + } + return NULL; +} + +/*******************************/ +/* B.1.2.2 Character Strings */ +/*******************************/ +void *print_datatypes_error_c::visit(double_byte_character_string_c *symbol) { + if (symbol->candidate_datatypes.size() == 0) { + STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for WSTRING data type."); + } else if (NULL == symbol->datatype) { + STAGE3_ERROR(symbol, symbol, "WSTRING data type not valid in this location."); + } + return NULL; +} + +void *print_datatypes_error_c::visit(single_byte_character_string_c *symbol) { + if (symbol->candidate_datatypes.size() == 0) { + STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for STRING data type."); + } else if (NULL == symbol->datatype) { + STAGE3_ERROR(symbol, symbol, "STRING data type not valid in this location."); + } + return NULL; +} + +/***************************/ +/* B 1.2.3 - Time Literals */ +/***************************/ +/************************/ +/* B 1.2.3.1 - Duration */ +/************************/ +void *print_datatypes_error_c::visit(duration_c *symbol) { + if (symbol->candidate_datatypes.size() == 0) { + STAGE3_ERROR(symbol, symbol, "Invalid syntax for TIME data type."); + } else if (NULL == symbol->datatype) { + STAGE3_ERROR(symbol, symbol, "TIME data type not valid in this location."); + } + return NULL; +} + +/************************************/ +/* B 1.2.3.2 - Time of day and Date */ +/************************************/ +void *print_datatypes_error_c::visit(time_of_day_c *symbol) { + if (symbol->candidate_datatypes.size() == 0) { + STAGE3_ERROR(symbol, symbol, "Invalid syntax for TOD data type."); + } else if (NULL == symbol->datatype) { + STAGE3_ERROR(symbol, symbol, "TOD data type not valid in this location."); + } + return NULL; +} + +void *print_datatypes_error_c::visit(date_c *symbol) { + if (symbol->candidate_datatypes.size() == 0) { + STAGE3_ERROR(symbol, symbol, "Invalid syntax for DATE data type."); + } else if (NULL == symbol->datatype) { + STAGE3_ERROR(symbol, symbol, "DATE data type not valid in this location."); + } + return NULL; +} + +void *print_datatypes_error_c::visit(date_and_time_c *symbol) { + if (symbol->candidate_datatypes.size() == 0) { + STAGE3_ERROR(symbol, symbol, "Invalid syntax for DT data type."); + } else if (NULL == symbol->datatype) { + STAGE3_ERROR(symbol, symbol, "DT data type not valid in this location."); + } + return NULL; +} + +/**********************/ +/* B 1.3 - Data types */ +/**********************/ +/********************************/ +/* B 1.3.3 - Derived data types */ +/********************************/ +void *print_datatypes_error_c::visit(data_type_declaration_c *symbol) { + // TODO !!! + /* for the moment we must return NULL so semantic analysis of remaining code is not interrupted! */ + return NULL; +} + +void *print_datatypes_error_c::visit(enumerated_value_c *symbol) { + if (symbol->candidate_datatypes.size() == 0) + STAGE3_ERROR(symbol, symbol, "Ambiguous enumerate value or Variable not declared in this scope."); + return NULL; +} + + +/*********************/ +/* B 1.4 - Variables */ +/*********************/ +void *print_datatypes_error_c::visit(symbolic_variable_c *symbol) { + if (symbol->candidate_datatypes.size() == 0) + STAGE3_ERROR(symbol, symbol, "Variable not declared in this scope."); + return NULL; +} + +/********************************************/ +/* B 1.4.1 - Directly Represented Variables */ +/********************************************/ +void *print_datatypes_error_c::visit(direct_variable_c *symbol) { + if (symbol->candidate_datatypes.size() == 0) + STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for located variable data type."); + return NULL; +} + +/*************************************/ +/* B 1.4.2 - Multi-element variables */ +/*************************************/ +/* subscripted_variable '[' subscript_list ']' */ +// SYM_REF2(array_variable_c, subscripted_variable, subscript_list) +void *print_datatypes_error_c::visit(array_variable_c *symbol) { + if (symbol->candidate_datatypes.size() == 0) + STAGE3_ERROR(symbol, symbol, "Array variable not declared in this scope."); + + /* recursively call the subscript list to print any errors in the expressions used in the subscript...*/ + symbol->subscript_list->accept(*this); + return NULL; +} + +/* subscript_list ',' subscript */ +// SYM_LIST(subscript_list_c) +/* NOTE: we inherit from iterator visitor, so we do not need to implement this method... */ +#if 0 +void *print_datatypes_error_c::visit(subscript_list_c *symbol) { +} +#endif + + +/* record_variable '.' field_selector */ +/* WARNING: input and/or output variables of function blocks + * may be accessed as fields of a structured variable! + * Code handling a structured_variable_c must take + * this into account! + */ +// SYM_REF2(structured_variable_c, record_variable, field_selector) +/* NOTE: We do not recursively determine the data types of each field_selector in fill_candidate_datatypes_c, + * so it does not make sense to recursively visit all the field_selectors to print out error messages. + * Maybe in the future, if we find the need to print out more detailed error messages, we might do it that way. For now, we don't! + */ +void *print_datatypes_error_c::visit(structured_variable_c *symbol) { + if (symbol->candidate_datatypes.size() == 0) + STAGE3_ERROR(symbol, symbol, "Structure variable not declared in this scope."); + return NULL; +} + +/************************************/ +/* B 1.5 Program organization units */ +/************************************/ +/*********************/ +/* B 1.5.1 Functions */ +/*********************/ +void *print_datatypes_error_c::visit(function_declaration_c *symbol) { + search_varfb_instance_type = new search_varfb_instance_type_c(symbol); + /* We do not check for data type errors in variable declarations, Skip this for now... */ +// symbol->var_declarations_list->accept(*this); + if (debug) printf("Print error data types list in body of function %s\n", ((token_c *)(symbol->derived_function_name))->value); + il_parenthesis_level = 0; + il_error = false; + prev_il_instruction = NULL; + symbol->function_body->accept(*this); + prev_il_instruction = NULL; + delete search_varfb_instance_type; + search_varfb_instance_type = NULL; + return NULL; +} + +/***************************/ +/* B 1.5.2 Function blocks */ +/***************************/ +void *print_datatypes_error_c::visit(function_block_declaration_c *symbol) { + search_varfb_instance_type = new search_varfb_instance_type_c(symbol); + /* We do not check for data type errors in variable declarations, Skip this for now... */ +// symbol->var_declarations->accept(*this); + if (debug) printf("Print error data types list in body of FB %s\n", ((token_c *)(symbol->fblock_name))->value); + il_parenthesis_level = 0; + il_error = false; + prev_il_instruction = NULL; + symbol->fblock_body->accept(*this); + prev_il_instruction = NULL; + delete search_varfb_instance_type; + search_varfb_instance_type = NULL; + return NULL; +} + +/**********************/ +/* B 1.5.3 - Programs */ +/**********************/ +void *print_datatypes_error_c::visit(program_declaration_c *symbol) { + search_varfb_instance_type = new search_varfb_instance_type_c(symbol); + /* We do not check for data type errors in variable declarations, Skip this for now... */ +// symbol->var_declarations->accept(*this); + if (debug) printf("Print error data types list in body of program %s\n", ((token_c *)(symbol->program_type_name))->value); + il_parenthesis_level = 0; + il_error = false; + prev_il_instruction = NULL; + symbol->function_block_body->accept(*this); + prev_il_instruction = NULL; + delete search_varfb_instance_type; + search_varfb_instance_type = NULL; + return NULL; +} + + + +/********************************/ +/* B 1.7 Configuration elements */ +/********************************/ +void *print_datatypes_error_c::visit(configuration_declaration_c *symbol) { +#if 0 + // TODO !!! + /* for the moment we must return NULL so semantic analysis of remaining code is not interrupted! */ +#endif + return NULL; +} + +/****************************************/ +/* B.2 - Language IL (Instruction List) */ +/****************************************/ +/***********************************/ +/* B 2.1 Instructions and Operands */ +/***********************************/ +// void *visit(instruction_list_c *symbol); +void *print_datatypes_error_c::visit(il_simple_operation_c *symbol) { + il_operand = symbol->il_operand; + if (NULL != symbol->il_operand) { + symbol->il_operand->accept(*this); + } + /* recursive call to see whether data types are compatible */ + symbol->il_simple_operator->accept(*this); + il_operand = NULL; + return NULL; +} + +void *print_datatypes_error_c::visit(il_function_call_c *symbol) { + return NULL; +} + +void *print_datatypes_error_c::visit(il_expression_c *symbol) { + return NULL; +} + +void *print_datatypes_error_c::visit(il_fb_call_c *symbol) { + return NULL; +} + +void *print_datatypes_error_c::visit(il_formal_funct_call_c *symbol) { + return NULL; +} + + +/* + void *visit(il_operand_list_c *symbol); + void *visit(simple_instr_list_c *symbol); + void *visit(il_param_list_c *symbol); + void *visit(il_param_assignment_c *symbol); + void *visit(il_param_out_assignment_c *symbol); + */ + +/*******************/ +/* B 2.2 Operators */ +/*******************/ +void *print_datatypes_error_c::visit(LD_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(LDN_operator_c *symbol) { + if (NULL != symbol->datatype) return NULL; + + il_operand->accept(*this); + if ((symbol->candidate_datatypes.size() == 0) && + (il_operand->candidate_datatypes.size() > 0)) + STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'LDN' operator."); + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(ST_operator_c *symbol) { + if (NULL != symbol->datatype) return NULL; + /* MANU: + * if prev_instruction is NULL we can print a message error or warning error like: + * we can't use a ST like first instruction. + * What do you think? + */ + il_operand->accept(*this); + if ((symbol->candidate_datatypes.size() == 0) && + (il_operand->candidate_datatypes.size() > 0)) + STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'ST' operator."); + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(STN_operator_c *symbol) { + if (NULL != symbol->datatype) return NULL; + /* MANU: + * if prev_instruction is NULL we can print a message error or warning error like: + * we can't use a ST like first instruction. + * What do you think? + */ + il_operand->accept(*this); + if ((symbol->candidate_datatypes.size() == 0) && + (il_operand->candidate_datatypes.size() > 0)) + STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'STN' operator."); + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(NOT_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(S_operator_c *symbol) { + if (NULL != symbol->datatype) return NULL; + + il_operand->accept(*this); + if ((symbol->candidate_datatypes.size() == 0) && + (il_operand->candidate_datatypes.size() > 0)) + STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'S' operator."); + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(R_operator_c *symbol) { + if (NULL != symbol->datatype) return NULL; + + il_operand->accept(*this); + if ((symbol->candidate_datatypes.size() == 0) && + (il_operand->candidate_datatypes.size() > 0)) + STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'R' operator."); + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(S1_operator_c *symbol) { + if (NULL != symbol->datatype) return NULL; + + il_operand->accept(*this); + if ((symbol->candidate_datatypes.size() == 0) && + (il_operand->candidate_datatypes.size() > 0)) + STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'S1' operator."); + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(R1_operator_c *symbol) { + if (NULL != symbol->datatype) return NULL; + + il_operand->accept(*this); + if ((symbol->candidate_datatypes.size() == 0) && + (il_operand->candidate_datatypes.size() > 0)) + STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'R1' operator."); + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(CLK_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(CU_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(CD_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(PV_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(IN_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(PT_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(AND_operator_c *symbol) { + if (NULL != symbol->datatype) return NULL; + + il_operand->accept(*this); + if ((symbol->candidate_datatypes.size() == 0) && + (il_operand->candidate_datatypes.size() > 0)) + STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'AND' operator."); + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(OR_operator_c *symbol) { + if (NULL != symbol->datatype) return NULL; + + il_operand->accept(*this); + if ((symbol->candidate_datatypes.size() == 0) && + (il_operand->candidate_datatypes.size() > 0)) + STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'OR' operator."); + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(XOR_operator_c *symbol) { + if (NULL != symbol->datatype) return NULL; + + il_operand->accept(*this); + if ((symbol->candidate_datatypes.size() == 0) && + (il_operand->candidate_datatypes.size() > 0)) + STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'XOR' operator."); + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(ANDN_operator_c *symbol) { + if (NULL != symbol->datatype) return NULL; + + il_operand->accept(*this); + if ((symbol->candidate_datatypes.size() == 0) && + (il_operand->candidate_datatypes.size() > 0)) + STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'ANDN' operator."); + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(ORN_operator_c *symbol) { + if (NULL != symbol->datatype) return NULL; + + il_operand->accept(*this); + if ((symbol->candidate_datatypes.size() == 0) && + (il_operand->candidate_datatypes.size() > 0)) + STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'ORN' operator."); + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(XORN_operator_c *symbol) { + if (NULL != symbol->datatype) return NULL; + + il_operand->accept(*this); + if ((symbol->candidate_datatypes.size() == 0) && + (il_operand->candidate_datatypes.size() > 0)) + STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'ORN' operator."); + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(ADD_operator_c *symbol) { + if (NULL != symbol->datatype) return NULL; + + il_operand->accept(*this); + if ((symbol->candidate_datatypes.size() == 0) && + (il_operand->candidate_datatypes.size() > 0)) + STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'ADD' operator."); + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(SUB_operator_c *symbol) { + if (NULL != symbol->datatype) return NULL; + + il_operand->accept(*this); + if ((symbol->candidate_datatypes.size() == 0) && + (il_operand->candidate_datatypes.size() > 0)) + STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'SUB' operator."); + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(MUL_operator_c *symbol) { + if (NULL != symbol->datatype) return NULL; + + il_operand->accept(*this); + if ((symbol->candidate_datatypes.size() == 0) && + (il_operand->candidate_datatypes.size() > 0)) + STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'MUL' operator."); + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(DIV_operator_c *symbol) { + if (NULL != symbol->datatype) return NULL; + + il_operand->accept(*this); + if ((symbol->candidate_datatypes.size() == 0) && + (il_operand->candidate_datatypes.size() > 0)) + STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'DIV' operator."); + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(MOD_operator_c *symbol) { + if (NULL != symbol->datatype) return NULL; + + il_operand->accept(*this); + if ((symbol->candidate_datatypes.size() == 0) && + (il_operand->candidate_datatypes.size() > 0)) + STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'MOD' operator."); + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(GT_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(GE_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(EQ_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(LT_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(LE_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(NE_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(CAL_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(CALC_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(CALCN_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(RET_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(RETC_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(RETCN_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(JMP_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(JMPC_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +void *print_datatypes_error_c::visit(JMPCN_operator_c *symbol) { + prev_il_instruction = symbol; + return NULL; +} + +/* Symbol class handled together with function call checks */ +// void *visit(il_assign_operator_c *symbol, variable_name); +/* Symbol class handled together with function call checks */ +// void *visit(il_assign_operator_c *symbol, option, variable_name); + +/***************************************/ +/* B.3 - Language ST (Structured Text) */ +/***************************************/ +/***********************/ +/* B 3.1 - Expressions */ +/***********************/ + +void *print_datatypes_error_c::visit(or_expression_c *symbol) { + if (NULL != symbol->datatype) return NULL; + + symbol->l_exp->accept(*this); + symbol->r_exp->accept(*this); + if ((symbol->candidate_datatypes.size() == 0) && + (symbol->l_exp->candidate_datatypes.size() > 0) && + (symbol->r_exp->candidate_datatypes.size() > 0)) + STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'OR' expression."); + return NULL; +} + + +void *print_datatypes_error_c::visit(xor_expression_c *symbol) { + if (NULL != symbol->datatype) return NULL; + + symbol->l_exp->accept(*this); + symbol->r_exp->accept(*this); + if ((symbol->candidate_datatypes.size() == 0) && + (symbol->l_exp->candidate_datatypes.size() > 0) && + (symbol->r_exp->candidate_datatypes.size() > 0)) + STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'XOR' expression."); + return NULL; +} + + +void *print_datatypes_error_c::visit(and_expression_c *symbol) { + if (NULL != symbol->datatype) return NULL; + + symbol->l_exp->accept(*this); + symbol->r_exp->accept(*this); + if ((symbol->candidate_datatypes.size() == 0) && + (symbol->l_exp->candidate_datatypes.size() > 0) && + (symbol->r_exp->candidate_datatypes.size() > 0)) + STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'AND' expression."); + return NULL; +} + + +void *print_datatypes_error_c::visit(equ_expression_c *symbol) { + if (NULL != symbol->datatype) return NULL; + + symbol->l_exp->accept(*this); + symbol->r_exp->accept(*this); + if ((symbol->candidate_datatypes.size() == 0) && + (symbol->l_exp->candidate_datatypes.size() > 0) && + (symbol->r_exp->candidate_datatypes.size() > 0)) + STAGE3_ERROR(symbol, symbol, "Data type mismatch for '=' expression."); + return NULL; +} + + +void *print_datatypes_error_c::visit(notequ_expression_c *symbol) { + if (NULL != symbol->datatype) return NULL; + + symbol->l_exp->accept(*this); + symbol->r_exp->accept(*this); + if ((symbol->candidate_datatypes.size() == 0) && + (symbol->l_exp->candidate_datatypes.size() > 0) && + (symbol->r_exp->candidate_datatypes.size() > 0)) + STAGE3_ERROR(symbol, symbol, "Data type mismatch for '<>' expression."); + return NULL; +} + + +void *print_datatypes_error_c::visit(lt_expression_c *symbol) { + if (NULL != symbol->datatype) return NULL; + + symbol->l_exp->accept(*this); + symbol->r_exp->accept(*this); + if ((symbol->candidate_datatypes.size() == 0) && + (symbol->l_exp->candidate_datatypes.size() > 0) && + (symbol->r_exp->candidate_datatypes.size() > 0)) + STAGE3_ERROR(symbol, symbol, "Data type mismatch for '<' expression."); + return NULL; +} + + +void *print_datatypes_error_c::visit(gt_expression_c *symbol) { + if (NULL != symbol->datatype) return NULL; + + symbol->l_exp->accept(*this); + symbol->r_exp->accept(*this); + if ((symbol->candidate_datatypes.size() == 0) && + (symbol->l_exp->candidate_datatypes.size() > 0) && + (symbol->r_exp->candidate_datatypes.size() > 0)) + STAGE3_ERROR(symbol, symbol, "Data type mismatch for '>' expression."); + return NULL; +} + + +void *print_datatypes_error_c::visit(le_expression_c *symbol) { + if (NULL != symbol->datatype) return NULL; + + symbol->l_exp->accept(*this); + symbol->r_exp->accept(*this); + if ((symbol->candidate_datatypes.size() == 0) && + (symbol->l_exp->candidate_datatypes.size() > 0) && + (symbol->r_exp->candidate_datatypes.size() > 0)) + STAGE3_ERROR(symbol, symbol, "Data type mismatch for '<=' expression."); + return NULL; +} + + +void *print_datatypes_error_c::visit(ge_expression_c *symbol) { + if (NULL != symbol->datatype) return NULL; + + symbol->l_exp->accept(*this); + symbol->r_exp->accept(*this); + if ((symbol->candidate_datatypes.size() == 0) && + (symbol->l_exp->candidate_datatypes.size() > 0) && + (symbol->r_exp->candidate_datatypes.size() > 0)) + STAGE3_ERROR(symbol, symbol, "Data type mismatch for '>=' expression."); + return NULL; +} + + +void *print_datatypes_error_c::visit(add_expression_c *symbol) { + if (NULL != symbol->datatype) return NULL; + + symbol->l_exp->accept(*this); + symbol->r_exp->accept(*this); + if ((symbol->candidate_datatypes.size() == 0) && + (symbol->l_exp->candidate_datatypes.size() > 0) && + (symbol->r_exp->candidate_datatypes.size() > 0)) + STAGE3_ERROR(symbol, symbol, "Current '+' result and operand not of same data type."); + + return NULL; +} + + + +void *print_datatypes_error_c::visit(sub_expression_c *symbol) { + if (NULL != symbol->datatype) return NULL; + + symbol->l_exp->accept(*this); + symbol->r_exp->accept(*this); + if ((symbol->candidate_datatypes.size() == 0) && + (symbol->l_exp->candidate_datatypes.size() > 0) && + (symbol->r_exp->candidate_datatypes.size() > 0)) + STAGE3_ERROR(symbol, symbol, "Current '-' result and operand not of same data type."); + return NULL; +} + +void *print_datatypes_error_c::visit(mul_expression_c *symbol) { + if (NULL != symbol->datatype) return NULL; + + symbol->l_exp->accept(*this); + symbol->r_exp->accept(*this); + if ((symbol->candidate_datatypes.size() == 0) && + (symbol->l_exp->candidate_datatypes.size() > 0) && + (symbol->r_exp->candidate_datatypes.size() > 0)) + STAGE3_ERROR(symbol, symbol, "Current '*' result and operand not of same data type."); + return NULL; +} + +void *print_datatypes_error_c::visit(div_expression_c *symbol) { + if (NULL != symbol->datatype) return NULL; + + symbol->l_exp->accept(*this); + symbol->r_exp->accept(*this); + if ((symbol->candidate_datatypes.size() == 0) && + (symbol->l_exp->candidate_datatypes.size() > 0) && + (symbol->r_exp->candidate_datatypes.size() > 0)) + STAGE3_ERROR(symbol, symbol, "Current '/' result and operand not of same data type."); + return NULL; +} + + +void *print_datatypes_error_c::visit(mod_expression_c *symbol) { + if (NULL != symbol->datatype) return NULL; + + symbol->l_exp->accept(*this); + symbol->r_exp->accept(*this); + if ((symbol->candidate_datatypes.size() == 0) && + (symbol->l_exp->candidate_datatypes.size() > 0) && + (symbol->r_exp->candidate_datatypes.size() > 0)) + STAGE3_ERROR(symbol, symbol, "Current 'MOD' result and operand not of same data type."); + return NULL; +} + + +void *print_datatypes_error_c::visit(power_expression_c *symbol) { + if (NULL != symbol->datatype) return NULL; + + symbol->l_exp->accept(*this); + symbol->r_exp->accept(*this); + if ((symbol->candidate_datatypes.size() == 0) && + (symbol->l_exp->candidate_datatypes.size() > 0) && + (symbol->r_exp->candidate_datatypes.size() > 0)) + STAGE3_ERROR(symbol, symbol, "Data type mismatch for '**' expression."); + return NULL; +} + + +void *print_datatypes_error_c::visit(neg_expression_c *symbol) { + if (NULL != symbol->datatype) return NULL; + + symbol->exp->accept(*this); + if ((symbol->candidate_datatypes.size() == 0) && + (symbol->exp->candidate_datatypes.size() > 0)) + STAGE3_ERROR(symbol, symbol, "Invalid data type for 'NEG' expression."); + return NULL; +} + + +void *print_datatypes_error_c::visit(not_expression_c *symbol) { + if (NULL != symbol->datatype) return NULL; + + symbol->exp->accept(*this); + if ((symbol->candidate_datatypes.size() == 0) && + (symbol->exp->candidate_datatypes.size() > 0)) + STAGE3_ERROR(symbol, symbol, "Invalid data type for 'NOT' expression."); + return NULL; +} + + +void *print_datatypes_error_c::visit(function_invocation_c *symbol) { + list_c *parameter_list; + function_declaration_c * f_decl; + + if (NULL != symbol->datatype) return NULL; + if (NULL != symbol->formal_param_list) + parameter_list = (list_c *)symbol->formal_param_list; + else if (NULL != symbol->nonformal_param_list) + parameter_list = (list_c *)symbol->nonformal_param_list; + else ERROR; + parameter_list->accept(*this); + if (symbol->candidate_datatypes.size() == 0) { + identifier_c *fname = (identifier_c *)symbol->function_name; + f_decl = (function_declaration_c *)symbol->called_function_declaration; + /* + * Manuele: In the future we have to test parameter number + * and show a specific message. + */ + STAGE3_ERROR(symbol, symbol, "No matching overloaded '%s' function call.", fname->value); + } + return NULL; +} + +/********************/ +/* B 3.2 Statements */ +/********************/ + +/*********************************/ +/* B 3.2.1 Assignment Statements */ +/*********************************/ +void *print_datatypes_error_c::visit(assignment_statement_c *symbol) { + symbol->l_exp->accept(*this); + symbol->r_exp->accept(*this); + if ((NULL == symbol->l_exp->datatype) && + (NULL == symbol->r_exp->datatype) && + (symbol->l_exp->candidate_datatypes.size() > 0) && + (symbol->r_exp->candidate_datatypes.size() > 0)) + STAGE3_ERROR(symbol, symbol, "Invalid data types for ':=' operation."); + return NULL; +} + +/********************************/ +/* B 3.2.3 Selection Statements */ +/********************************/ + +void *print_datatypes_error_c::visit(if_statement_c *symbol) { + symbol->expression->accept(*this); + if ((NULL == symbol->expression->datatype) && + (symbol->expression->candidate_datatypes.size() > 0)) { + STAGE3_ERROR(symbol, symbol, "Invalid data type for 'IF' condition."); + } + if (NULL != symbol->statement_list) + symbol->statement_list->accept(*this); + if (NULL != symbol->elseif_statement_list) + symbol->elseif_statement_list->accept(*this); + if (NULL != symbol->else_statement_list) + symbol->else_statement_list->accept(*this); + return NULL; +} + +void *print_datatypes_error_c::visit(elseif_statement_c *symbol) { + symbol->expression->accept(*this); + if ((NULL == symbol->expression->datatype) && + (symbol->expression->candidate_datatypes.size() > 0)) { + STAGE3_ERROR(symbol, symbol, "Invalid data type for 'ELSIF' condition."); + } + if (NULL != symbol->statement_list) + symbol->statement_list->accept(*this); + return NULL; +} + + +void *print_datatypes_error_c::visit(case_statement_c *symbol) { + symbol->expression->accept(*this); + if ((NULL == symbol->expression->datatype) && + (symbol->expression->candidate_datatypes.size() > 0)) { + STAGE3_ERROR(symbol, symbol, "'CASE' quantity not an integer or enumerated."); + } + symbol->case_element_list->accept(*this); + if (NULL != symbol->statement_list) + symbol->statement_list->accept(*this); + return NULL; +} + +/********************************/ +/* B 3.2.4 Iteration Statements */ +/********************************/ + +void *print_datatypes_error_c::visit(for_statement_c *symbol) { + symbol->control_variable->accept(*this); + symbol->beg_expression->accept(*this); + symbol->end_expression->accept(*this); + /* Control variable */ + if ((NULL == symbol->control_variable->datatype) && + (symbol->control_variable->candidate_datatypes.size() > 0)) { + STAGE3_ERROR(symbol, symbol, "Invalid data type for 'FOR' control variable."); + } + /* BEG expression */ + if ((NULL == symbol->beg_expression->datatype) && + (symbol->beg_expression->candidate_datatypes.size() > 0)) { + STAGE3_ERROR(symbol, symbol, "Invalid data type for 'FOR' begin expression."); + } + /* END expression */ + if ((NULL == symbol->end_expression->datatype) && + (symbol->end_expression->candidate_datatypes.size() > 0)) { + STAGE3_ERROR(symbol, symbol, "Invalid data type for 'FOR' end expression."); + } + /* BY expression */ + if ((NULL != symbol->by_expression) && + (NULL == symbol->by_expression->datatype) && + (symbol->end_expression->candidate_datatypes.size() > 0)) { + STAGE3_ERROR(symbol, symbol, "Invalid data type for 'FOR' by expression."); + } + /* DO statement */ + if (NULL != symbol->statement_list) + symbol->statement_list->accept(*this); + + return NULL; +} + +void *print_datatypes_error_c::visit(while_statement_c *symbol) { + symbol->expression->accept(*this); + if (symbol->candidate_datatypes.size() != 1) { + STAGE3_ERROR(symbol, symbol, "Invalid data type for 'WHILE' condition."); + return NULL; + } + if (NULL != symbol->statement_list) + symbol->statement_list->accept(*this); + return NULL; +} + +void *print_datatypes_error_c::visit(repeat_statement_c *symbol) { + if (symbol->candidate_datatypes.size() != 1) { + STAGE3_ERROR(symbol, symbol, "Invalid data type for 'REPEAT' condition."); + return NULL; + } + if (NULL != symbol->statement_list) + symbol->statement_list->accept(*this); + symbol->expression->accept(*this); + return NULL; +} + + + + + diff -r 0c2ef191b22a -r d48f53715f77 stage3/print_datatypes_error.hh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stage3/print_datatypes_error.hh Wed Feb 01 19:49:11 2012 +0000 @@ -0,0 +1,303 @@ +/* + * matiec - a compiler for the programming languages defined in IEC 61131-3 + * + * Copyright (C) 2009-2011 Mario de Sousa (msousa@fe.up.pt) + * Copyright (C) 2011-2012 Manuele Conti (manuele.conti@sirius-es.it) + * Copyright (C) 2011-2012 Matteo Facchinetti (matteo.facchinetti@sirius-es.it) + * + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * This code is made available on the understanding that it will not be + * used in safety-critical situations without a full and competent review. + */ + +/* + * An IEC 61131-3 compiler. + * + * Based on the + * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10) + * + */ + + +#include "../absyntax_utils/absyntax_utils.hh" + +class print_datatypes_error_c: public iterator_visitor_c { + + private: + search_varfb_instance_type_c *search_varfb_instance_type; + search_base_type_c search_base_type; + /* When calling a function block, we must first find it's type, + * by searching through the declarations of the variables currently + * in scope. + * This class does just that... + * A new object instance is instantiated whenever we start checking semantics + * for a function block type declaration, or a program declaration. + * This object instance will then later be called while the + * function block's or the program's body is being handled. + * + * Note that functions cannot contain calls to function blocks, + * so we do not create an object instance when handling + * a function declaration. + */ + + /* In IL code, once we find a type mismatch error, it is best to + * ignore any further errors until the end of the logical operation, + * i.e. until the next LD. + * However, we cannot clear the il_error flag on all LD operations, + * as these may also be used within parenthesis. LD operations + * within parenthesis may not clear the error flag. + * We therefore need a counter to know how deep inside a parenthesis + * structure we are. + */ + int il_parenthesis_level; + bool il_error; + bool error_found; + + /* the current data type of the data stored in the IL stack, i.e. the default variable */ + symbol_c *prev_il_instruction; + /* the current IL operand being analyzed - its symbol and its data type */ + symbol_c *il_operand_type; + symbol_c *il_operand; + + + public: + print_datatypes_error_c(symbol_c *ignore); + virtual ~print_datatypes_error_c(void); + int get_error_found(); + + /* a helper function... */ + symbol_c *base_type(symbol_c *symbol); + + /*********************/ + /* B 1.2 - Constants */ + /*********************/ + /******************************/ + /* B 1.2.1 - Numeric Literals */ + /******************************/ + void *visit(real_c *symbol); + void *visit(integer_c *symbol); + void *visit(neg_real_c *symbol); + void *visit(neg_integer_c *symbol); + void *visit(binary_integer_c *symbol); + void *visit(octal_integer_c *symbol); + void *visit(hex_integer_c *symbol); + void *visit(integer_literal_c *symbol); + void *visit(real_literal_c *symbol); + void *visit(bit_string_literal_c *symbol); + void *visit(boolean_literal_c *symbol); + void *visit(boolean_true_c *symbol); + void *visit(boolean_false_c *symbol); + + /*******************************/ + /* B.1.2.2 Character Strings */ + /*******************************/ + void *visit(double_byte_character_string_c *symbol); + void *visit(single_byte_character_string_c *symbol); + + /***************************/ + /* B 1.2.3 - Time Literals */ + /***************************/ + /************************/ + /* B 1.2.3.1 - Duration */ + /************************/ + void *visit(duration_c *symbol); + + /************************************/ + /* B 1.2.3.2 - Time of day and Date */ + /************************************/ + void *visit(time_of_day_c *symbol); + void *visit(date_c *symbol); + void *visit(date_and_time_c *symbol); + + /**********************/ + /* B 1.3 - Data types */ + /**********************/ + /********************************/ + /* B 1.3.3 - Derived data types */ + /********************************/ + void *visit(data_type_declaration_c *symbol); + void *visit(enumerated_value_c *symbol); + + /*********************/ + /* B 1.4 - Variables */ + /*********************/ + void *visit(symbolic_variable_c *symbol); + + /********************************************/ + /* B 1.4.1 - Directly Represented Variables */ + /********************************************/ + void *visit(direct_variable_c *symbol); + + /*************************************/ + /* B 1.4.2 - Multi-element variables */ + /*************************************/ + void *visit(array_variable_c *symbol); + void *visit(structured_variable_c *symbol); + + /**************************************/ + /* B 1.5 - Program organization units */ + /**************************************/ + /***********************/ + /* B 1.5.1 - Functions */ + /***********************/ + void *visit(function_declaration_c *symbol); + + /*****************************/ + /* B 1.5.2 - Function blocks */ + /*****************************/ + void *visit(function_block_declaration_c *symbol); + + /**********************/ + /* B 1.5.3 - Programs */ + /**********************/ + void *visit(program_declaration_c *symbol); + + /********************************/ + /* B 1.7 Configuration elements */ + /********************************/ + void *visit(configuration_declaration_c *symbol); + + /****************************************/ + /* B.2 - Language IL (Instruction List) */ + /****************************************/ + /***********************************/ + /* B 2.1 Instructions and Operands */ + /***********************************/ + // void *visit(instruction_list_c *symbol); + void *visit(il_simple_operation_c *symbol); + void *visit(il_function_call_c *symbol); + void *visit(il_expression_c *symbol); + void *visit(il_fb_call_c *symbol); + void *visit(il_formal_funct_call_c *symbol); + /* + void *visit(il_operand_list_c *symbol); + void *visit(simple_instr_list_c *symbol); + void *visit(il_param_list_c *symbol); + void *visit(il_param_assignment_c *symbol); + void *visit(il_param_out_assignment_c *symbol); + */ + + /*******************/ + /* B 2.2 Operators */ + /*******************/ + void *visit(LD_operator_c *symbol); + void *visit(LDN_operator_c *symbol); + void *visit(ST_operator_c *symbol); + void *visit(STN_operator_c *symbol); + void *visit(NOT_operator_c *symbol); + void *visit(S_operator_c *symbol); + void *visit(R_operator_c *symbol); + void *visit(S1_operator_c *symbol); + void *visit(R1_operator_c *symbol); + void *visit(CLK_operator_c *symbol); + void *visit(CU_operator_c *symbol); + void *visit(CD_operator_c *symbol); + void *visit(PV_operator_c *symbol); + void *visit(IN_operator_c *symbol); + void *visit(PT_operator_c *symbol); + void *visit(AND_operator_c *symbol); + void *visit(OR_operator_c *symbol); + void *visit(XOR_operator_c *symbol); + void *visit(ANDN_operator_c *symbol); + void *visit(ORN_operator_c *symbol); + void *visit(XORN_operator_c *symbol); + void *visit(ADD_operator_c *symbol); + void *visit(SUB_operator_c *symbol); + void *visit(MUL_operator_c *symbol); + void *visit(DIV_operator_c *symbol); + void *visit(MOD_operator_c *symbol); + void *visit(GT_operator_c *symbol); + void *visit(GE_operator_c *symbol); + void *visit(EQ_operator_c *symbol); + void *visit(LT_operator_c *symbol); + void *visit(LE_operator_c *symbol); + void *visit(NE_operator_c *symbol); + void *visit(CAL_operator_c *symbol); + void *visit(CALC_operator_c *symbol); + void *visit(CALCN_operator_c *symbol); + void *visit(RET_operator_c *symbol); + void *visit(RETC_operator_c *symbol); + void *visit(RETCN_operator_c *symbol); + void *visit(JMP_operator_c *symbol); + void *visit(JMPC_operator_c *symbol); + void *visit(JMPCN_operator_c *symbol); + /* Symbol class handled together with function call checks */ + // void *visit(il_assign_operator_c *symbol, variable_name); + /* Symbol class handled together with function call checks */ + // void *visit(il_assign_operator_c *symbol, option, variable_name); + + /***************************************/ + /* B.3 - Language ST (Structured Text) */ + /***************************************/ + /***********************/ + /* B 3.1 - Expressions */ + /***********************/ + void *visit(or_expression_c *symbol); + void *visit(xor_expression_c *symbol); + void *visit(and_expression_c *symbol); + void *visit(equ_expression_c *symbol); + void *visit(notequ_expression_c *symbol); + void *visit(lt_expression_c *symbol); + void *visit(gt_expression_c *symbol); + void *visit(le_expression_c *symbol); + void *visit(ge_expression_c *symbol); + void *visit(add_expression_c *symbol); + void *visit(sub_expression_c *symbol); + void *visit(mul_expression_c *symbol); + void *visit(div_expression_c *symbol); + void *visit(mod_expression_c *symbol); + void *visit(power_expression_c *symbol); + void *visit(neg_expression_c *symbol); + void *visit(not_expression_c *symbol); + void *visit(function_invocation_c *symbol); + + /*********************************/ + /* B 3.2.1 Assignment Statements */ + /*********************************/ + void *visit(assignment_statement_c *symbol); + + /*****************************************/ + /* B 3.2.2 Subprogram Control Statements */ + /*****************************************/ + //void *visit(fb_invocation_c *symbol); + + /********************************/ + /* B 3.2.3 Selection Statements */ + /********************************/ + void *visit(if_statement_c *symbol); + // void *visit(elseif_statement_list_c *symbol); + void *visit(elseif_statement_c *symbol); + void *visit(case_statement_c *symbol); + // void *visit(case_element_list_c *symbol); + // void *visit(case_element_c *symbol); + // void *visit(case_list_c *symbol); + + /********************************/ + /* B 3.2.4 Iteration Statements */ + /********************************/ + void *visit(for_statement_c *symbol); + void *visit(while_statement_c *symbol); + void *visit(repeat_statement_c *symbol); + +}; // print_datatypes_error_c + + + + + + + diff -r 0c2ef191b22a -r d48f53715f77 stage3/stage3.cc --- a/stage3/stage3.cc Wed Feb 01 13:01:08 2012 +0000 +++ b/stage3/stage3.cc Wed Feb 01 19:49:11 2012 +0000 @@ -1,8 +1,10 @@ /* * matiec - a compiler for the programming languages defined in IEC 61131-3 * - * Copyright (C) 2009-2011 Mario de Sousa (msousa@fe.up.pt) + * Copyright (C) 2009-2012 Mario de Sousa (msousa@fe.up.pt) * Copyright (C) 2007-2011 Laurent Bessard and Edouard Tisserant + * Copyright (C) 2012 Manuele Conti (manuele.conti@sirius-es.it) + * Copyright (C) 2012 Matteo Facchinetti (matteo.facchinetti@sirius-es.it) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -32,14 +34,20 @@ #include "stage3.hh" +#include "fill_candidate_datatypes.hh" +#include "narrow_candidate_datatypes.hh" +#include "print_datatypes_error.hh" + + int type_safety(symbol_c *tree_root){ - visit_expression_type_c visit_expression_type(tree_root); - - (*tree_root).accept(visit_expression_type); - - if (visit_expression_type.get_error_found()) - return -1; - + fill_candidate_datatypes_c fill_candidate_datatypes(tree_root); + tree_root->accept(fill_candidate_datatypes); + narrow_candidate_datatypes_c narrow_candidate_datatypes(tree_root); + tree_root->accept(narrow_candidate_datatypes); + print_datatypes_error_c print_datatypes_error(tree_root); + tree_root->accept(print_datatypes_error); + if (print_datatypes_error.get_error_found()) + return -1; return 0; } diff -r 0c2ef191b22a -r d48f53715f77 stage3/stage3.hh --- a/stage3/stage3.hh Wed Feb 01 13:01:08 2012 +0000 +++ b/stage3/stage3.hh Wed Feb 01 19:49:11 2012 +0000 @@ -31,19 +31,7 @@ */ -// #include /* required for NULL */ -#include -#include -#include -#include -#include -#include - #include "../util/symtable.hh" -#include "../util/dsymtable.hh" -#include "../absyntax/visitor.hh" - -#include "visit_expression_type.hh" int stage3(symbol_c *tree_root); diff -r 0c2ef191b22a -r d48f53715f77 stage3/visit_expression_type.cc --- a/stage3/visit_expression_type.cc Wed Feb 01 13:01:08 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2291 +0,0 @@ -/* - * matiec - a compiler for the programming languages defined in IEC 61131-3 - * - * Copyright (C) 2009-2011 Mario de Sousa (msousa@fe.up.pt) - * Copyright (C) 2007-2011 Laurent Bessard and Edouard Tisserant - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * - * This code is made available on the understanding that it will not be - * used in safety-critical situations without a full and competent review. - */ - -/* - * An IEC 61131-3 compiler. - * - * Based on the - * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10) - * - */ - - -/* Verify whether the semantic rules of data type compatibility are being followed. - * - * For example: - */ - -#include "visit_expression_type.hh" -#include -#include -#include -#include -#include - - -#define FIRST_(symbol1, symbol2) (((symbol1)->first_order < (symbol2)->first_order) ? (symbol1) : (symbol2)) -#define LAST_(symbol1, symbol2) (((symbol1)->last_order > (symbol2)->last_order) ? (symbol1) : (symbol2)) - -#define STAGE3_ERROR(symbol1, symbol2, ...) { \ - fprintf(stderr, "%s:%d-%d..%d-%d: error : ", \ - FIRST_(symbol1,symbol2)->first_file, FIRST_(symbol1,symbol2)->first_line, FIRST_(symbol1,symbol2)->first_column, \ - LAST_(symbol1,symbol2) ->last_line, LAST_(symbol1,symbol2) ->last_column); \ - fprintf(stderr, __VA_ARGS__); \ - fprintf(stderr, "\n"); \ - il_error = true; \ - error_found = true; \ - } - - -/* set to 1 to see debug info during execution */ -static int debug = 0; - - -void *visit_expression_type_c::visit(program_declaration_c *symbol) { - search_varfb_instance_type = new search_varfb_instance_type_c(symbol); - symbol->var_declarations->accept(*this); - if (debug) printf("checking semantics in body of program %s\n", ((token_c *)(symbol->program_type_name))->value); - il_parenthesis_level = 0; - il_error = false; - il_default_variable_type = NULL; - symbol->function_block_body->accept(*this); - il_default_variable_type = NULL; - delete search_varfb_instance_type; - search_varfb_instance_type = NULL; - return NULL; -} - -void *visit_expression_type_c::visit(function_declaration_c *symbol) { - search_varfb_instance_type = new search_varfb_instance_type_c(symbol); - symbol->var_declarations_list->accept(*this); - if (debug) printf("checking semantics in body of function %s\n", ((token_c *)(symbol->derived_function_name))->value); - il_parenthesis_level = 0; - il_error = false; - il_default_variable_type = NULL; - symbol->function_body->accept(*this); - il_default_variable_type = NULL; - delete search_varfb_instance_type; - search_varfb_instance_type = NULL; - return NULL; -} - -void *visit_expression_type_c::visit(function_block_declaration_c *symbol) { - search_varfb_instance_type = new search_varfb_instance_type_c(symbol); - symbol->var_declarations->accept(*this); - if (debug) printf("checking semantics in body of FB %s\n", ((token_c *)(symbol->fblock_name))->value); - il_parenthesis_level = 0; - il_error = false; - il_default_variable_type = NULL; - symbol->fblock_body->accept(*this); - il_default_variable_type = NULL; - delete search_varfb_instance_type; - search_varfb_instance_type = NULL; - return NULL; -} - - - - - - - - - -visit_expression_type_c::visit_expression_type_c(symbol_c *ignore) { - error_found = false; -} - -visit_expression_type_c::~visit_expression_type_c(void) { -} - -bool visit_expression_type_c::get_error_found(void) { - return error_found; -} - - - -/* NOTE on data type handling and literals... - * ========================================== - * - * Literals that are explicitly type cast - * e.g.: BYTE#42 - * INT#65 - * TIME#45h23m - * etc... - * are NOT considered literals in the following code. - * Since they are type cast, and their data type is fixed and well known, - * they are treated as a variable of that data type (except when determining lvalues) - * In other words, when calling search_constant_type_c on these constants, it returns - * a xxxxx_type_name_c, and not one of the xxxx_literal_c ! - * - * When the following code handles a literal, it is really a literal of unknown data type. - * e.g. 42, may be considered an int, a byte, a word, etc... - * - * NOTE: type_symbol == NULL is valid! - * This will occur, for example, when and undefined/undeclared symbolic_variable is used in the program. - * This will not be of any type, so we always return false. - */ - -/* A helper function... */ -bool visit_expression_type_c::is_ANY_ELEMENTARY_type(symbol_c *type_symbol) { - if (type_symbol == NULL) {return false;} - return is_ANY_MAGNITUDE_type(type_symbol) - || is_ANY_BIT_type (type_symbol) - || is_ANY_STRING_type (type_symbol) - || is_ANY_DATE_type (type_symbol); -} - -/* A helper function... */ -bool visit_expression_type_c::is_ANY_SAFEELEMENTARY_type(symbol_c *type_symbol) { - if (type_symbol == NULL) {return false;} - return is_ANY_SAFEMAGNITUDE_type(type_symbol) - || is_ANY_SAFEBIT_type (type_symbol) - || is_ANY_SAFESTRING_type (type_symbol) - || is_ANY_SAFEDATE_type (type_symbol); -} - -/* A helper function... */ -bool visit_expression_type_c::is_ANY_ELEMENTARY_compatible(symbol_c *type_symbol) { - if (type_symbol == NULL) {return false;} - /* NOTE: doing - * return is_ANY_SAFEELEMENTARY_type() || is_ANY_ELEMENTARY_type() - * is incorrect, as the literals would never be considered compatible... - */ - return is_ANY_MAGNITUDE_compatible(type_symbol) - || is_ANY_BIT_compatible (type_symbol) - || is_ANY_STRING_compatible (type_symbol) - || is_ANY_DATE_compatible (type_symbol); -} - - -/* A helper function... */ -bool visit_expression_type_c::is_ANY_MAGNITUDE_type(symbol_c *type_symbol) { - if (type_symbol == NULL) {return false;} - if (typeid(*type_symbol) == typeid(time_type_name_c)) {return true;} - return is_ANY_NUM_type(type_symbol); -} - -/* A helper function... */ -bool visit_expression_type_c::is_ANY_SAFEMAGNITUDE_type(symbol_c *type_symbol) { - if (type_symbol == NULL) {return false;} - if (typeid(*type_symbol) == typeid(safetime_type_name_c)) {return true;} - return is_ANY_SAFENUM_type(type_symbol); -} - -/* A helper function... */ -bool visit_expression_type_c::is_ANY_MAGNITUDE_compatible(symbol_c *type_symbol) { - if (type_symbol == NULL) {return false;} - if (is_ANY_MAGNITUDE_type (type_symbol)) {return true;} - if (is_ANY_SAFEMAGNITUDE_type(type_symbol)) {return true;} - - return is_ANY_NUM_compatible(type_symbol); -} - -/* A helper function... */ -bool visit_expression_type_c::is_ANY_NUM_type(symbol_c *type_symbol) { - if (type_symbol == NULL) {return false;} - if (is_ANY_REAL_type(type_symbol)) {return true;} - if (is_ANY_INT_type(type_symbol)) {return true;} - return false; -} - -/* A helper function... */ -bool visit_expression_type_c::is_ANY_SAFENUM_type(symbol_c *type_symbol) { - if (type_symbol == NULL) {return false;} - return is_ANY_SAFEREAL_type(type_symbol) - || is_ANY_SAFEINT_type (type_symbol); -} - -/* A helper function... */ -bool visit_expression_type_c::is_ANY_NUM_compatible(symbol_c *type_symbol) { - if (type_symbol == NULL) {return false;} - if (is_ANY_REAL_compatible(type_symbol)) {return true;} - if (is_ANY_INT_compatible(type_symbol)) {return true;} - return false; -} - -/* A helper function... */ -bool visit_expression_type_c::is_ANY_DATE_type(symbol_c *type_symbol) { - if (type_symbol == NULL) {return false;} - if (typeid(*type_symbol) == typeid(date_type_name_c)) {return true;} - if (typeid(*type_symbol) == typeid(tod_type_name_c)) {return true;} - if (typeid(*type_symbol) == typeid(dt_type_name_c)) {return true;} - return false; -} - -/* A helper function... */ -bool visit_expression_type_c::is_ANY_SAFEDATE_type(symbol_c *type_symbol) { - if (type_symbol == NULL) {return false;} - if (typeid(*type_symbol) == typeid(safedate_type_name_c)) {return true;} - if (typeid(*type_symbol) == typeid(safetod_type_name_c)) {return true;} - if (typeid(*type_symbol) == typeid(safedt_type_name_c)) {return true;} - return false; -} - -/* A helper function... */ -bool visit_expression_type_c::is_ANY_DATE_compatible(symbol_c *type_symbol) { - if (type_symbol == NULL) {return false;} - if (is_ANY_DATE_type (type_symbol)) {return true;} - if (is_ANY_SAFEDATE_type(type_symbol)) {return true;} - return false; -} - -/* A helper function... */ -bool visit_expression_type_c::is_ANY_STRING_type(symbol_c *type_symbol) { - if (type_symbol == NULL) {return false;} - if (typeid(*type_symbol) == typeid(string_type_name_c)) {return true;} - if (typeid(*type_symbol) == typeid(wstring_type_name_c)) {return true;} -// TODO literal_string ??? - return false; -} - -/* A helper function... */ -bool visit_expression_type_c::is_ANY_SAFESTRING_type(symbol_c *type_symbol) { - if (type_symbol == NULL) {return false;} - if (typeid(*type_symbol) == typeid(safestring_type_name_c)) {return true;} - if (typeid(*type_symbol) == typeid(safewstring_type_name_c)) {return true;} - return false; -} - -/* A helper function... */ -bool visit_expression_type_c::is_ANY_STRING_compatible(symbol_c *type_symbol) { - if (type_symbol == NULL) {return false;} - if (is_ANY_STRING_type (type_symbol)) {return true;} - if (is_ANY_SAFESTRING_type(type_symbol)) {return true;} - return false; -} - -/* A helper function... */ -bool visit_expression_type_c::is_ANY_INT_type(symbol_c *type_symbol) { - if (type_symbol == NULL) {return false;} - if (typeid(*type_symbol) == typeid(sint_type_name_c)) {return true;} - if (typeid(*type_symbol) == typeid(int_type_name_c)) {return true;} - if (typeid(*type_symbol) == typeid(dint_type_name_c)) {return true;} - if (typeid(*type_symbol) == typeid(lint_type_name_c)) {return true;} - if (typeid(*type_symbol) == typeid(usint_type_name_c)) {return true;} - if (typeid(*type_symbol) == typeid(uint_type_name_c)) {return true;} - if (typeid(*type_symbol) == typeid(udint_type_name_c)) {return true;} - if (typeid(*type_symbol) == typeid(ulint_type_name_c)) {return true;} - return false; -} - -/* A helper function... */ -bool visit_expression_type_c::is_ANY_SAFEINT_type(symbol_c *type_symbol) { - if (type_symbol == NULL) {return false;} - if (typeid(*type_symbol) == typeid(safesint_type_name_c)) {return true;} - if (typeid(*type_symbol) == typeid(safeint_type_name_c)) {return true;} - if (typeid(*type_symbol) == typeid(safedint_type_name_c)) {return true;} - if (typeid(*type_symbol) == typeid(safelint_type_name_c)) {return true;} - if (typeid(*type_symbol) == typeid(safeusint_type_name_c)) {return true;} - if (typeid(*type_symbol) == typeid(safeuint_type_name_c)) {return true;} - if (typeid(*type_symbol) == typeid(safeudint_type_name_c)) {return true;} - if (typeid(*type_symbol) == typeid(safeulint_type_name_c)) {return true;} - return false; -} - -/* A helper function... */ -bool visit_expression_type_c::is_ANY_INT_compatible(symbol_c *type_symbol) { - if (type_symbol == NULL) {return false;} - if (is_ANY_INT_type (type_symbol)) {return true;} - if (is_ANY_SAFEINT_type(type_symbol)) {return true;} - if (is_literal_integer_type(type_symbol)) {return true;} - return false; -} - -/* A helper function... */ -bool visit_expression_type_c::is_ANY_REAL_type(symbol_c *type_symbol) { - if (type_symbol == NULL) {return false;} - if (typeid(*type_symbol) == typeid(real_type_name_c)) {return true;} - if (typeid(*type_symbol) == typeid(lreal_type_name_c)) {return true;} - return false; -} - -/* A helper function... */ -bool visit_expression_type_c::is_ANY_SAFEREAL_type(symbol_c *type_symbol) { - if (type_symbol == NULL) {return false;} - if (typeid(*type_symbol) == typeid(safereal_type_name_c)) {return true;} - if (typeid(*type_symbol) == typeid(safelreal_type_name_c)) {return true;} - return false; -} - -/* A helper function... */ -bool visit_expression_type_c::is_ANY_REAL_compatible(symbol_c *type_symbol) { - if (type_symbol == NULL) {return false;} - if (is_ANY_REAL_type (type_symbol)) {return true;} - if (is_ANY_SAFEREAL_type(type_symbol)) {return true;} - if (is_literal_real_type(type_symbol)) {return true;} - return false; -} - -/* A helper function... */ -bool visit_expression_type_c::is_ANY_BIT_type(symbol_c *type_symbol) { - if (type_symbol == NULL) {return false;} - if (typeid(*type_symbol) == typeid(bool_type_name_c)) {return true;} - if (typeid(*type_symbol) == typeid(byte_type_name_c)) {return true;} - if (typeid(*type_symbol) == typeid(word_type_name_c)) {return true;} - if (typeid(*type_symbol) == typeid(dword_type_name_c)) {return true;} - if (typeid(*type_symbol) == typeid(lword_type_name_c)) {return true;} - return false; -} - -/* A helper function... */ -bool visit_expression_type_c::is_ANY_SAFEBIT_type(symbol_c *type_symbol) { - if (type_symbol == NULL) {return false;} - if (typeid(*type_symbol) == typeid(safebool_type_name_c)) {return true;} - if (typeid(*type_symbol) == typeid(safebyte_type_name_c)) {return true;} - if (typeid(*type_symbol) == typeid(safeword_type_name_c)) {return true;} - if (typeid(*type_symbol) == typeid(safedword_type_name_c)) {return true;} - if (typeid(*type_symbol) == typeid(safelword_type_name_c)) {return true;} - return false; -} - -/* A helper function... */ -bool visit_expression_type_c::is_ANY_BIT_compatible(symbol_c *type_symbol) { - if (type_symbol == NULL) {return false;} - if (is_ANY_BIT_type (type_symbol)) {return true;} - if (is_ANY_SAFEBIT_type(type_symbol)) {return true;} - if (is_nonneg_literal_integer_type(type_symbol)) {return true;} - if (is_literal_bool_type(type_symbol)) {return true;} - return false; -} - -/* A helper function... */ -bool visit_expression_type_c::is_BOOL_type(symbol_c *type_symbol) { - if (type_symbol == NULL) {return false;} - if (typeid(*type_symbol) == typeid(bool_type_name_c)) {return true;} - return false; -} - -/* A helper function... */ -bool visit_expression_type_c::is_SAFEBOOL_type(symbol_c *type_symbol){ - if (type_symbol == NULL) {return false;} - if (typeid(*type_symbol) == typeid(safebool_type_name_c)) {return true;} - return false; -} - -/* A helper function... */ -bool visit_expression_type_c::is_ANY_BOOL_compatible(symbol_c *type_symbol) { - if (type_symbol == NULL) {return false;} - if (is_BOOL_type (type_symbol)) {return true;} - if (is_SAFEBOOL_type(type_symbol)) {return true;} - if (is_literal_bool_type(type_symbol)) {return true;} - return false; -} - - -#define is_type(type_name_symbol, type_name_class) ((type_name_symbol == NULL) ? false : (typeid(*type_name_symbol) == typeid(type_name_class))) - - -#define sizeoftype(symbol) get_sizeof_datatype_c::getsize(symbol) - - -/* A helper function... */ -bool visit_expression_type_c::is_literal_integer_type(symbol_c *type_symbol) { - if (type_symbol == NULL) {return false;} - if (typeid(*type_symbol) == typeid(neg_integer_c)) {return true;} - return is_nonneg_literal_integer_type(type_symbol); -} - - -/* A helper function... */ -bool visit_expression_type_c::is_nonneg_literal_integer_type(symbol_c *type_symbol) { - if (type_symbol == NULL) {return false;} - if (typeid(*type_symbol) == typeid(integer_c)) {return true;} - if (typeid(*type_symbol) == typeid(binary_integer_c)) {return true;} - if (typeid(*type_symbol) == typeid(octal_integer_c)) {return true;} - if (typeid(*type_symbol) == typeid(hex_integer_c)) {return true;} - return false; -} - - -/* A helper function... */ -bool visit_expression_type_c::is_literal_real_type(symbol_c *type_symbol) { - if (type_symbol == NULL) {return false;} - if (typeid(*type_symbol) == typeid(real_c)) {return true;} - if (typeid(*type_symbol) == typeid(neg_real_c)) {return true;} - return false; -} - - -/* A helper function... */ -bool visit_expression_type_c::is_literal_bool_type(symbol_c *type_symbol) { - bool_type_name_c bool_t; - - if (type_symbol == NULL) {return false;} - if (typeid(*type_symbol) == typeid(boolean_true_c)) {return true;} - if (typeid(*type_symbol) == typeid(boolean_false_c)) {return true;} - if (is_nonneg_literal_integer_type(type_symbol)) - if (sizeoftype(&bool_t) >= sizeoftype(type_symbol)) {return true;} - return false; -} - -bool visit_expression_type_c::is_ANY_ELEMENTARY_OR_ENUMERATED_compatible(symbol_c *type_symbol) { - if (type_symbol == NULL) {return false;} - if (search_base_type.type_is_enumerated(type_symbol)) {return true;} - return is_ANY_ELEMENTARY_compatible(type_symbol); -} - - -/* Determine the common data type between two data types. - * If no common data type found, return NULL. - * - * If data types are identical, return the first (actually any would do...). - * If any of the data types is a literal, we confirm that - * the literal uses less bits than the fixed size data type. - * e.g. BYTE and 1024 returns NULL - * BYTE and 255 returns BYTE - * - * If two literals, then return the literal that requires more bits... - */ - -symbol_c *visit_expression_type_c::common_type__(symbol_c *first_type, symbol_c *second_type) { - if (first_type == NULL && second_type == NULL) {return NULL;} - if (first_type == NULL) {return second_type;} - if (second_type == NULL) {return first_type;} - - if (is_literal_integer_type(first_type) && is_literal_integer_type(second_type)) - {return ((sizeoftype(first_type) > sizeoftype(second_type))? first_type:second_type);} - - if (is_literal_real_type(first_type) && is_literal_real_type(second_type)) - {return ((sizeoftype(first_type) > sizeoftype(second_type))? first_type:second_type);} - - if (is_literal_bool_type(first_type) && is_literal_bool_type(second_type)) - {return first_type;} - - /* The following check can only be made after the is_literal_XXXX checks */ - /* When two literals of the same type, with identical typeid's are checked, - * we must return the one that occupies more bits... This is done above. - */ - if (typeid(*first_type) == typeid(*second_type)) {return first_type;} - - /* NOTE Although a BOOL is also an ANY_BIT, we must check it explicitly since some - * literal bool values are not literal integers... - */ - if (is_BOOL_type(first_type) && is_literal_bool_type(second_type)) {return first_type;} - if (is_BOOL_type(second_type) && is_literal_bool_type(first_type)) {return second_type;} - - if (is_SAFEBOOL_type(first_type) && is_literal_bool_type(second_type)) {return first_type;} - if (is_SAFEBOOL_type(second_type) && is_literal_bool_type(first_type)) {return second_type;} - - if (is_SAFEBOOL_type(first_type) && is_BOOL_type(second_type)) {return second_type;} - if (is_SAFEBOOL_type(second_type) && is_BOOL_type(first_type)) {return first_type;} - - if (is_ANY_BIT_type(first_type) && is_nonneg_literal_integer_type(second_type)) - {return ((sizeoftype(first_type) >= sizeoftype(second_type))? first_type :NULL);} - if (is_ANY_BIT_type(second_type) && is_nonneg_literal_integer_type(first_type)) - {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);} - - if (is_ANY_SAFEBIT_type(first_type) && is_nonneg_literal_integer_type(second_type)) - {return ((sizeoftype(first_type) >= sizeoftype(second_type))? first_type :NULL);} - if (is_ANY_SAFEBIT_type(second_type) && is_nonneg_literal_integer_type(first_type)) - {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);} - - if (is_ANY_SAFEBIT_type(first_type) && is_ANY_BIT_type(second_type)) - {return ((sizeoftype(first_type) == sizeoftype(second_type))? second_type:NULL);} - if (is_ANY_SAFEBIT_type(second_type) && is_ANY_BIT_type(first_type)) - {return ((sizeoftype(first_type) == sizeoftype(second_type))? first_type :NULL);} - - if (is_ANY_INT_type(first_type) && is_literal_integer_type(second_type)) - {return ((sizeoftype(first_type) >= sizeoftype(second_type))? first_type :NULL);} - if (is_ANY_INT_type(second_type) && is_literal_integer_type(first_type)) - {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);} - - if (is_ANY_SAFEINT_type(first_type) && is_literal_integer_type(second_type)) - {return ((sizeoftype(first_type) >= sizeoftype(second_type))? first_type :NULL);} - if (is_ANY_SAFEINT_type(second_type) && is_literal_integer_type(first_type)) - {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);} - - if (is_ANY_SAFEINT_type(first_type) && is_ANY_INT_type(second_type)) - {return ((sizeoftype(first_type) == sizeoftype(second_type))? second_type:NULL);} - if (is_ANY_SAFEINT_type(second_type) && is_ANY_INT_type(first_type)) - {return ((sizeoftype(first_type) == sizeoftype(second_type))? first_type :NULL);} - - if (is_ANY_REAL_type(first_type) && is_literal_real_type(second_type)) - {return ((sizeoftype(first_type) >= sizeoftype(second_type))? first_type :NULL);} - if (is_ANY_REAL_type(second_type) && is_literal_real_type(first_type)) - {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);} - - if (is_ANY_SAFEREAL_type(first_type) && is_literal_real_type(second_type)) - {return ((sizeoftype(first_type) >= sizeoftype(second_type))? first_type :NULL);} - if (is_ANY_SAFEREAL_type(second_type) && is_literal_real_type(first_type)) - {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);} - - if (is_ANY_SAFEREAL_type(first_type) && is_ANY_REAL_type(second_type)) - {return ((sizeoftype(first_type) == sizeoftype(second_type))? second_type:NULL);} - if (is_ANY_SAFEREAL_type(second_type) && is_ANY_REAL_type(first_type)) - {return ((sizeoftype(first_type) == sizeoftype(second_type))? first_type :NULL);} - - /* the Time and Date types... */ - if (is_type(first_type, safetime_type_name_c) && is_type(second_type, time_type_name_c)) {return second_type;} - if (is_type(second_type, safetime_type_name_c) && is_type( first_type, time_type_name_c)) {return first_type;} - - if (is_type(first_type, safedate_type_name_c) && is_type(second_type, date_type_name_c)) {return second_type;} - if (is_type(second_type, safedate_type_name_c) && is_type( first_type, date_type_name_c)) {return first_type;} - - if (is_type(first_type, safedt_type_name_c) && is_type(second_type, dt_type_name_c)) {return second_type;} - if (is_type(second_type, safedt_type_name_c) && is_type( first_type, dt_type_name_c)) {return first_type;} - - if (is_type(first_type, safetod_type_name_c) && is_type(second_type, tod_type_name_c)) {return second_type;} - if (is_type(second_type, safetod_type_name_c) && is_type( first_type, tod_type_name_c)) {return first_type;} - - /* no common type */ - return NULL; -} - -/* Determine the common data type between two data types. - * Unlike the common_type__() function, we stop the compiler with an ERROR - * if no common data type is found. - */ -symbol_c *visit_expression_type_c::common_type(symbol_c *first_type, symbol_c *second_type) { -/* - symbol_c *res = common_type__(first_type, second_type); - if (NULL == res) ERROR; - return res; -*/ - return common_type__(first_type, second_type); -} - - -/* Return TRUE if the second (value) data type may be assigned to a variable of the first (variable) data type - * such as: - * var_type value_type - * BOOL BYTE#7 -> returns false - * INT INT#7 -> returns true - * INT 7 -> returns true - * REAL 7.89 -> returns true - * REAL 7 -> returns true - * INT 7.89 -> returns false - * SAFEBOOL BOOL#1 -> returns false !!! - * etc... - * - * NOTE: It is assumed that the var_type is the data type of an lvalue - */ -bool visit_expression_type_c::is_valid_assignment(symbol_c *var_type, symbol_c *value_type) { - if (var_type == NULL) {/* STAGE3_ERROR(value_type, value_type, "Var_type == NULL"); */ return false;} - if (value_type == NULL) {/* STAGE3_ERROR(var_type, var_type, "Value_type == NULL"); */ return false;} - - symbol_c *common_type = common_type__(var_type, value_type); - if (NULL == common_type) - return false; - return (typeid(*var_type) == typeid(*common_type)); -} - - -/* Return TRUE if there is a common data type, otherwise return FALSE - * i.e., return TRUE if both data types may be used simultaneously in an expression - * such as: - * BOOL#0 AND BYTE#7 -> returns false - * 0 AND BYTE#7 -> returns true - * INT#10 AND INT#7 -> returns true - * INT#10 AND 7 -> returns true - * REAL#34.3 AND 7.89 -> returns true - * REAL#34.3 AND 7 -> returns true - * INT#10 AND 7.89 -> returns false - * SAFEBOOL#0 AND BOOL#1 -> returns true !!! - * etc... - */ -bool visit_expression_type_c::is_compatible_type(symbol_c *first_type, symbol_c *second_type) { - if (first_type == NULL || second_type == NULL) {return false;} - return (NULL != common_type__(first_type, second_type)); -} - - - - -/* A helper function... */ -/* -symbol_c *visit_expression_type_c::compute_boolean_expression(symbol_c *left_type, symbol_c *right_type, - is_data_type_t is_data_type) { -*/ -symbol_c *visit_expression_type_c::compute_expression(symbol_c *left_type, symbol_c *right_type, is_data_type_t is_data_type, - symbol_c *left_expr, symbol_c *right_expr) { - bool error = false; - - if (!(this->*is_data_type)(left_type)) { - if (debug) printf("visit_expression_type_c::compute_expression(): invalid left_type\n"); - if (left_expr != NULL) - STAGE3_ERROR(left_expr, left_expr, "Invalid data type of operand, or of data resulting from previous IL instructions."); - error = true; - } - if (!(this->*is_data_type)(right_type)) { - if (debug) printf("visit_expression_type_c::compute_expression(): invalid right_type\n"); - if (right_expr != NULL) - STAGE3_ERROR(right_expr, right_expr, "Invalid data type of operand."); - error = true; - } - if (!is_compatible_type(left_type, right_type)) { - if (debug) printf("visit_expression_type_c::compute_expression(): left_type & right_type are incompatible\n"); - if ((left_expr != NULL) && (right_expr != NULL)) - STAGE3_ERROR(left_expr, right_expr, "Type mismatch between operands."); - error = true; - } - - if (error) - return NULL; - else - return common_type(left_type, right_type); -} - - - - -/* A helper function... */ -/* check the semantics of a FB or Function non-formal call */ -/* e.g. foo(1, 2, 3, 4); */ -/* If error_count pointer is != NULL, we do not really print out the errors, - * but rather only count how many errors were found. - * This is used to support overloaded functions, where we have to check each possible - * function, one at a time, untill we find a function call without any errors. - */ -void visit_expression_type_c::check_nonformal_call(symbol_c *f_call, symbol_c *f_decl, bool use_il_defvar, int *error_count) { - symbol_c *call_param_value, *call_param_type, *param_type; - identifier_c *param_name; - function_param_iterator_c fp_iterator(f_decl); - function_call_param_iterator_c fcp_iterator(f_call); - int extensible_parameter_highest_index = -1; - - /* reset error counter */ - if (error_count != NULL) *error_count = 0; - /* if use_il_defvar, then the first parameter for the call comes from the il_default_variable */ - if (use_il_defvar) { - /* The first parameter of the function corresponds to the il_default_variable_type of the function call */ - do { - param_name = fp_iterator.next(); - if(param_name == NULL) break; - /* The EN and ENO parameters are default parameters. - * In the non-formal invocation of a function there can be no assignment of - * values to these parameters. Therefore, we ignore the parameters declared - * in the function. - */ - } while ((strcmp(param_name->value, "EN") == 0) || (strcmp(param_name->value, "ENO") == 0)); - /* If the function does not have any parameters (param_name == NULL) - * then we cannot compare its type with the il_default_variable_type. - * - * However, I (Mario) think this is invalid syntax, as it seems to me all functions must - * have at least one parameter. - * However, we will make this semantic verification consider it possible, as later - * versions of the standard may change that syntax. - * So, instead of generating a syntax error message, we simply check whether the call - * is passing any more parameters besides the default variable (the il default variable may be ignored - * in this case, and not consider it as being a parameter being passed to the function). - * If it does, then we have found a semantic error, otherwise the function call is - * correct, and we simply return. - */ - if(param_name == NULL) { - if (fcp_iterator.next_nf() != NULL) - STAGE3_ERROR(f_call, f_call, "Too many parameters in function/FB call."); - return; - } else { - /* param_name != NULL */ - param_type = fp_iterator.param_type(); - if(!is_valid_assignment(param_type, il_default_variable_type)) { - if (error_count != NULL) (*error_count)++; - else STAGE3_ERROR(f_call, f_call, "In function/FB call, first parameter has invalid data type."); - } - } - - /* the fisrt parameter (il_def_variable) is correct */ - if (extensible_parameter_highest_index < fp_iterator.extensible_param_index()) { - extensible_parameter_highest_index = fp_iterator.extensible_param_index(); - } - } // if (use_il_defvar) - - - - /* Iterating through the non-formal parameters of the function call */ - while((call_param_value = fcp_iterator.next_nf()) != NULL) { - /* Obtaining the type of the value being passed in the function call */ - call_param_type = base_type((symbol_c*)call_param_value->accept(*this)); - if (call_param_type == NULL) { - if (error_count != NULL) (*error_count)++; - /* the following error will usually occur when ST code uses an identifier, that could refer to an enumerated constant, - * but was not actually used as a constant in any definitions of an enumerated data type - */ - else STAGE3_ERROR(call_param_value, call_param_value, "Could not determine data type of value being passed in function/FB call."); - continue; - } - - /* Iterate to the next parameter of the function being called. - * Get the name of that parameter, and ignore if EN or ENO. - */ - do { - param_name = fp_iterator.next(); - /* If there is no other parameter declared, then we are passing too many parameters... */ - if(param_name == NULL) { - if (error_count != NULL) (*error_count)++; - /* Note: We don't want to print out the follwoing error message multiple times, so we return instead of continuing with 'break' */ - else STAGE3_ERROR(f_call, f_call, "Too many parameters in function/FB call."); return; - } - } while ((strcmp(param_name->value, "EN") == 0) || (strcmp(param_name->value, "ENO") == 0)); - - /* Get the parameter type */ - param_type = base_type(fp_iterator.param_type()); - /* If the declared parameter and the parameter from the function call do not have the same type */ - if(!is_valid_assignment(param_type, call_param_type)) { - if (error_count != NULL) (*error_count)++; - else STAGE3_ERROR(call_param_value, call_param_value, "Type mismatch in function/FB call parameter."); - } - - if (extensible_parameter_highest_index < fp_iterator.extensible_param_index()) { - extensible_parameter_highest_index = fp_iterator.extensible_param_index(); - } - } - - /* The function call may not have any errors! */ - /* In the case of a call to an extensible function, we store the highest index - * of the extensible parameters this particular call uses, in the symbol_c object - * of the function call itself! - * In calls to non-extensible functions, this value will be set to -1. - * This information is later used in stage4 to correctly generate the - * output code. - */ - int extensible_param_count = -1; - if (extensible_parameter_highest_index >=0) /* if call to extensible function */ - extensible_param_count = 1 + extensible_parameter_highest_index - fp_iterator.first_extensible_param_index(); - il_function_call_c *il_function_call = dynamic_cast(f_call); - function_invocation_c *function_invocation = dynamic_cast(f_call); - if (il_function_call != NULL) il_function_call ->extensible_param_count = extensible_param_count; - else if (function_invocation != NULL) function_invocation->extensible_param_count = extensible_param_count; - // else ERROR; /* this function is also called by Function Blocks, so this is not an error! */ -} - - -/* check semantics of FB call in the IL language using input operators */ -/* e.g. CU, CLK, IN, PT, SR, ... */ -void visit_expression_type_c::check_il_fbcall(symbol_c *il_operator, const char *il_operator_str) { - symbol_c *call_param_type = il_default_variable_type; - symbol_c *fb_decl = il_operand_type; - /* The following should never occur. The function block must be defined, - * and the FB type being called MUST be in the symtable... - * This was all already checked at stage 2! - */ - if (NULL == fb_decl) ERROR; - if (call_param_type == NULL) ERROR; - - /* We also create an identifier_c object, so we can later use it to find the equivalent FB parameter */ - /* Note however that this symbol does not have the correct location (file name and line numbers) - * so any error messages must use the il_operator symbol to generate the error location - */ - identifier_c call_param_name(il_operator_str); - - /* Obtaining the type of the value being passed in the function call */ - call_param_type = base_type(call_param_type); - if (call_param_type == NULL) STAGE3_ERROR(il_operator, il_operator, "Could not determine data type of value being passed in FB call."); - - /* Find the corresponding parameter of the function being called */ - function_param_iterator_c fp_iterator(fb_decl); - if(fp_iterator.search(&call_param_name) == NULL) { - STAGE3_ERROR(il_operand, il_operand, "Called FB does not have an input parameter named %s.", il_operator_str); - } else { - /* Get the parameter type */ - symbol_c *param_type = base_type(fp_iterator.param_type()); - /* If the declared parameter and the parameter from the function call have the same type */ - if(!is_valid_assignment(param_type, call_param_type)) STAGE3_ERROR(il_operator, il_operator, "Type mismatch in FB call parameter."); - } -} - - -/* A helper function... */ -/* check the semantics of a FB or Function formal call */ -/* e.g. foo(IN1 := 1, OUT1 =>x, EN := true); */ -/* If error_count pointer is != NULL, we do not really print out the errors, - * but rather only count how many errors were found. - * This is used to support overloaded functions, where we have to check each possible - * function, one at a time, untill we find a function call without any errors. - */ -void visit_expression_type_c::check_formal_call(symbol_c *f_call, symbol_c *f_decl, int *error_count) { - symbol_c *call_param_value, *call_param_type, *call_param_name, *param_type; - symbol_c *verify_duplicate_param; - identifier_c *param_name; - function_param_iterator_c fp_iterator(f_decl); - function_call_param_iterator_c fcp_iterator(f_call); - int extensible_parameter_highest_index = -1; - identifier_c *extensible_parameter_name; - - /* reset error counter */ - if (error_count != NULL) *error_count = 0; - - /* Iterating through the formal parameters of the function call */ - while((call_param_name = fcp_iterator.next_f()) != NULL) { - - /* Obtaining the value being passed in the function call */ - call_param_value = fcp_iterator.get_current_value(); - /* the following should never occur. If it does, then we have a bug in our code... */ - if (NULL == call_param_value) ERROR; - - /* Checking if there are duplicated parameter values */ - verify_duplicate_param = fcp_iterator.search_f(call_param_name); - if(verify_duplicate_param != call_param_value){ - if (error_count != NULL) (*error_count)++; - else STAGE3_ERROR(call_param_name, verify_duplicate_param, "Duplicated parameter values."); - } - - /* Obtaining the type of the value being passed in the function call */ - call_param_type = (symbol_c*)call_param_value->accept(*this); - if (call_param_type == NULL) { - if (error_count != NULL) (*error_count)++; - else STAGE3_ERROR(call_param_name, call_param_value, "Could not determine data type of value being passed in function/FB call."); - /* The data value being passed is possibly any enumerated type value. - * We do not yet handle semantic verification of enumerated types. - */ - ERROR; - } - call_param_type = base_type(call_param_type); - if (call_param_type == NULL) STAGE3_ERROR(call_param_name, call_param_value, "Could not determine data type of value being passed in function/FB call."); - - /* Find the corresponding parameter of the function being called */ - param_name = fp_iterator.search(call_param_name); - if(param_name == NULL) { - if (error_count != NULL) (*error_count)++; - else STAGE3_ERROR(call_param_name, call_param_name, "Invalid parameter in function/FB call."); - } else { - /* Get the parameter type */ - param_type = base_type(fp_iterator.param_type()); - /* If the declared parameter and the parameter from the function call have the same type */ - if(!is_valid_assignment(param_type, call_param_type)) { - if (error_count != NULL) (*error_count)++; - else STAGE3_ERROR(call_param_name, call_param_value, "Type mismatch function/FB call parameter."); - } - if (extensible_parameter_highest_index < fp_iterator.extensible_param_index()) { - extensible_parameter_highest_index = fp_iterator.extensible_param_index(); - extensible_parameter_name = param_name; - } - } - } - - /* In the case of a call to an extensible function, we store the highest index - * of the extensible parameters this particular call uses, in the symbol_c object - * of the function call itself! - * In calls to non-extensible functions, this value will be set to -1. - * This information is later used in stage4 to correctly generate the - * output code. - */ - int extensible_param_count = -1; - if (extensible_parameter_highest_index >=0) /* if call to extensible function */ - extensible_param_count = 1 + extensible_parameter_highest_index - fp_iterator.first_extensible_param_index(); - il_formal_funct_call_c *il_formal_funct_call = dynamic_cast(f_call); - function_invocation_c *function_invocation = dynamic_cast(f_call); - if (il_formal_funct_call != NULL) il_formal_funct_call->extensible_param_count = extensible_param_count; - else if (function_invocation != NULL) function_invocation->extensible_param_count = extensible_param_count; -// else ERROR; /* this function is also called by Function Blocks, so this is not an error! */ - - /* We have iterated through all the formal parameters of the function call, - * and everything seems fine. - * If the function being called in an extensible function, we now check - * whether the extensible paramters in the formal invocation do not skip - * any indexes... - * - * f(in1:=0, in2:=0, in4:=0) --> ERROR!! - */ - if (extensible_parameter_highest_index >=0) { /* if call to extensible function */ - for (int i=fp_iterator.first_extensible_param_index(); i < extensible_parameter_highest_index; i++) { - char tmp[256]; - if (snprintf(tmp, 256, "%s%d", extensible_parameter_name->value, i) >= 256) ERROR; - if (fcp_iterator.search_f(tmp) == NULL) { - /* error in invocation of extensible function */ - if (error_count != NULL) (*error_count)++; - else STAGE3_ERROR(f_call, f_call, "Missing extensible parameters in call to extensible function."); - } - } - } -} - - - - -/* a helper function... */ -symbol_c *visit_expression_type_c::base_type(symbol_c *symbol) { - /* NOTE: symbol == NULL is valid. It will occur when, for e.g., an undefined/undeclared symbolic_variable is used - * in the code. - */ - if (symbol == NULL) return NULL; - return (symbol_c *)symbol->accept(search_base_type); -} - - -/* a helper function... */ -void *visit_expression_type_c::verify_null(symbol_c *symbol){ - if(il_default_variable_type == NULL){ - STAGE3_ERROR(symbol, symbol, "Missing LD instruction (or equivalent) before this instruction."); - } - if(il_operand_type == NULL){ - STAGE3_ERROR(symbol, symbol, "This instruction requires an operand."); - } - return NULL; -} - - -/********************************/ -/* B 1.3.3 - Derived data types */ -/********************************/ -void *visit_expression_type_c::visit(data_type_declaration_c *symbol) { - // TODO !!! - /* for the moment we must return NULL so semantic analysis of remaining code is not interrupted! */ - return NULL; -} - - -/*********************/ -/* B 1.4 - Variables */ -/*********************/ - -void *visit_expression_type_c::visit(symbolic_variable_c *symbol) { - return search_varfb_instance_type->get_basetype_decl(symbol); -} - -/********************************************/ -/* B 1.4.1 - Directly Represented Variables */ -/********************************************/ -void *visit_expression_type_c::visit(direct_variable_c *symbol) { - switch (symbol->value[2]) { - case 'X': // bit - 1 bit - return (void *)&bool_type_name; - case 'B': // byte - 8 bits - return (void *)&byte_type_name; - case 'W': // word - 16 bits - return (void *)&word_type_name; - case 'D': // double word - 32 bits - return (void *)&dword_type_name; - case 'L': // long word - 64 bits - return (void *)&lword_type_name; - default: // if none of the above, then the empty string was used <=> boolean - return (void *)&bool_type_name; - } -} - -/*************************************/ -/* B 1.4.2 - Multi-element variables */ -/*************************************/ -void *visit_expression_type_c::visit(array_variable_c *symbol) { - return search_varfb_instance_type->get_basetype_decl(symbol); -} - -void *visit_expression_type_c::visit(structured_variable_c *symbol) { - return search_varfb_instance_type->get_basetype_decl(symbol); -} - - - -/********************************/ -/* B 1.7 Configuration elements */ -/********************************/ -void *visit_expression_type_c::visit(configuration_declaration_c *symbol) { - // TODO !!! - /* for the moment we must return NULL so semantic analysis of remaining code is not interrupted! */ - return NULL; -} - - -/****************************************/ -/* B.2 - Language IL (Instruction List) */ -/****************************************/ -/***********************************/ -/* B 2.1 Instructions and Operands */ -/***********************************/ -/*| instruction_list il_instruction */ -/* The visitor of the base class search_visitor_c will handle calling each instruction in the list. - * We do not need to do anything here... - */ -// void *visit_expression_type_c::visit(instruction_list_c *symbol) - -/* | label ':' [il_incomplete_instruction] eol_list */ -//SYM_REF2(il_instruction_c, label, il_instruction) -// void *visit_expression_type_c::visit(il_instruction_c *symbol); - - -/* | il_simple_operator [il_operand] */ -// SYM_REF2(il_simple_operation_c, il_simple_operator, il_operand) -void *visit_expression_type_c::visit(il_simple_operation_c *symbol) { - if (il_error) - return NULL; - - /* determine the data type of the operand */ - il_operand = symbol->il_operand; - if (symbol->il_operand != NULL){ - il_operand_type = base_type((symbol_c *)symbol->il_operand->accept(*this)); - } else { - il_operand_type = NULL; - } - /* recursive call to see whether data types are compatible */ - symbol->il_simple_operator->accept(*this); - - il_operand_type = NULL; - il_operand = NULL; - return NULL; -} - -// | function_name [il_operand_list] */ -//SYM_REF2(il_function_call_c, function_name, il_operand_list) -void *visit_expression_type_c::visit(il_function_call_c *symbol) { - if (il_error) - return NULL; - - symbol_c *return_data_type = NULL; - - /* First find the declaration of the function being called! */ - function_symtable_t::iterator lower = function_symtable.lower_bound(symbol->function_name); - function_symtable_t::iterator upper = function_symtable.upper_bound(symbol->function_name); - if (lower == function_symtable.end()) ERROR; - - int error_count = 0; - int *error_count_ptr = NULL; - - function_symtable_t::iterator second = lower; - second++; - if (second != upper) - /* This is a call to an overloaded function... */ - error_count_ptr = &error_count; - - for(; lower != upper; lower++) { - function_declaration_c *f_decl = function_symtable.get_value(lower); - - check_nonformal_call(symbol, f_decl, true, error_count_ptr); - - if (0 == error_count) { - /* Either: - * (i) we have a call to a non-overloaded function (error_cnt_ptr is NULL!, so error_count won't change!) - * (ii) we have a call to an overloaded function, with no errors! - */ - - /* Store the pointer to the declaration of the function being called. - * This data will be used by stage 4 to call the correct function. - * Mostly needed to disambiguate overloaded functions... - * See comments in absyntax.def for more details - */ - symbol->called_function_declaration = f_decl; - /* determine the base data type returned by the function being called... */ - return_data_type = base_type(f_decl->type_name); - /* If the following occurs, then we must have some big bug in the syntax parser (stage 2)... */ - if (NULL == return_data_type) ERROR; - /* set the new data type of the default variable for the following verifications... */ - il_default_variable_type = return_data_type; - return NULL; - } - } - - /* No compatible function was found for this function call */ - STAGE3_ERROR(symbol, symbol, "Call to an overloaded function with invalid parameter type."); - return NULL; -} - - -/* | il_expr_operator '(' [il_operand] eol_list [simple_instr_list] ')' */ -// SYM_REF3(il_expression_c, il_expr_operator, il_operand, simple_instr_list); -void *visit_expression_type_c::visit(il_expression_c *symbol) { - if (il_error) - return NULL; - - symbol_c *il_default_variable_type_back = il_default_variable_type; - - il_parenthesis_level++; - - if(symbol->il_operand != NULL) { - il_default_variable_type = base_type((symbol_c *)symbol->il_operand->accept(*this)); - } else { - il_default_variable_type = NULL; - } - - if(symbol->simple_instr_list != NULL) { - symbol->simple_instr_list->accept(*this); - } - - il_parenthesis_level--; - if (il_parenthesis_level < 0) ERROR; - - il_operand = symbol->simple_instr_list; - il_operand_type = il_default_variable_type; - il_default_variable_type = il_default_variable_type_back; - - /* Now check the if the data type semantics of operation are correct, - * but only if no previous error has been found... - */ - if (!il_error) - symbol->il_expr_operator->accept(*this); - - il_operand_type = NULL; - il_operand = NULL; - return NULL; -} - - -#if 0 -/* il_jump_operator label */ -SYM_REF2(il_jump_operation_c, il_jump_operator, label) -void *visit_expression_type_c::visit(il_jump_operation_c *symbol); -#endif - - -/* il_call_operator prev_declared_fb_name - * | il_call_operator prev_declared_fb_name '(' ')' - * | il_call_operator prev_declared_fb_name '(' eol_list ')' - * | il_call_operator prev_declared_fb_name '(' il_operand_list ')' - * | il_call_operator prev_declared_fb_name '(' eol_list il_param_list ')' - */ -/* SYM_REF4(il_fb_call_c, il_call_operator, fb_name, il_operand_list, il_param_list) */ -void *visit_expression_type_c::visit(il_fb_call_c *symbol) { - if (il_error) - return NULL; - - /* first check whether the il_default_variable is of the correct type - * for the CAL / CALC / CALCN operator being used... - */ - symbol->il_call_operator->accept(*this); - - /* Now check the FB call itself... */ - - /* First we find the declaration of the FB type of the FB instance being called... */ - /* e.g. Function_block foo_fb_type - * ... - * End_Function_Block - * - * Program test - * var fb1 : foo_fb_type; end_var - * fb1(...) - * End_Program - * - * search_varfb_instance_type->get_basetype_decl( identifier_c("fb1") ) - * in the scope of Program 'test' - * will return the fb declaration of foo_fb_type !! - */ -#if 0 - symbol_c *fb_decl_symbol = search_varfb_instance_type->get_basetype_decl(symbol->fb_name); - /* The following should never occur. The function block must be defined, - * and the FB type being called MUST be in the symtable... - * This was all already checked at stage 2! - */ - if (NULL == fb_decl_symbol) ERROR; - - function_block_declaration_c *fb_decl = dynamic_cast(fb_decl_symbol); - /* should never occur. ... */ - if (NULL == fb_decl) ERROR; -#endif - symbol_c *fb_decl = search_varfb_instance_type->get_basetype_decl(symbol->fb_name); - /* The following should never occur. The function block must be defined, - * and the FB type being called MUST be in the symtable... - * This was all already checked at stage 2! - */ - if (NULL == fb_decl) ERROR; - - /* now check the semantics of the fb call... */ - /* If the syntax parser is working correctly, exactly one of the - * following two symbols will be NULL, while the other is != NULL. - */ - if (NULL != symbol->il_operand_list) check_nonformal_call(symbol, fb_decl); - if (NULL != symbol->il_param_list) check_formal_call (symbol, fb_decl); - - return NULL; -} - - - -/* | function_name '(' eol_list [il_param_list] ')' */ -/* SYM_REF2(il_formal_funct_call_c, function_name, il_param_list) */ -void *visit_expression_type_c::visit(il_formal_funct_call_c *symbol) { - if (il_error) - return NULL; - - symbol_c *return_data_type = NULL; - function_symtable_t::iterator lower = function_symtable.lower_bound(symbol->function_name); - function_symtable_t::iterator upper = function_symtable.upper_bound(symbol->function_name); - - if (lower == function_symtable.end()) { - function_type_t current_function_type = get_function_type((identifier_c *)symbol->function_name); - if (current_function_type == function_none) ERROR; - return NULL; - } - - int error_count = 0; - int *error_count_ptr = NULL; - - function_symtable_t::iterator second = lower; - second++; - if (second != upper) - /* This is a call to an overloaded function... */ - error_count_ptr = &error_count; - - for(; lower != upper; lower++) { - function_declaration_c *f_decl = function_symtable.get_value(lower); - - /* check semantics of data passed in the function call... */ - check_formal_call(symbol, f_decl, error_count_ptr); - - if (0 == error_count) { - /* Either: - * (i) we have a call to a non-overloaded function (error_cnt_ptr is NULL!, so error_count won't change!) - * (ii) we have a call to an overloaded function, with no errors! - */ - - /* Store the pointer to the declaration of the function being called. - * This data will be used by stage 4 to call the correct function. - * Mostly needed to disambiguate overloaded functions... - * See comments in absyntax.def for more details - */ - symbol->called_function_declaration = f_decl; - /* determine the base data type returned by the function being called... */ - return_data_type = base_type(f_decl->type_name); - /* the following should never occur. If it does, then we have a bug in the syntax parser (stage 2)... */ - if (NULL == return_data_type) ERROR; - /* the data type of the data returned by the function, and stored in the il default variable... */ - il_default_variable_type = return_data_type; - return NULL; - } - } - - /* No compatible function was found for this function call */ - STAGE3_ERROR(symbol, symbol, "Call to an overloaded function with invalid parameter type."); - return NULL; -} - - -#if 0 -/* | il_operand_list ',' il_operand */ -SYM_LIST(il_operand_list_c) -void *visit_expression_type_c::visit(il_operand_list_c *symbol); - -/* | simple_instr_list il_simple_instruction */ -SYM_LIST(simple_instr_list_c) -void *visit_expression_type_c::visit(simple_instr_list_c *symbol); - -/* | il_initial_param_list il_param_instruction */ -SYM_LIST(il_param_list_c) -void *visit_expression_type_c::visit(il_param_list_c *symbol); - -/* il_assign_operator il_operand - * | il_assign_operator '(' eol_list simple_instr_list ')' - */ -SYM_REF3(il_param_assignment_c, il_assign_operator, il_operand, simple_instr_list) -void *visit_expression_type_c::visit(il_param_assignment_c *symbol); -/* il_assign_out_operator variable */ -SYM_REF2(il_param_out_assignment_c, il_assign_out_operator, variable) -void *visit_expression_type_c::visit(il_param_out_assignment_c *symbol); - -#endif - - -/*******************/ -/* B 2.2 Operators */ -/*******************/ - -//SYM_REF0(LD_operator_c) -void *visit_expression_type_c::visit(LD_operator_c *symbol) { - if (0 == il_parenthesis_level) - il_error = false; - - if(il_operand_type == NULL) - STAGE3_ERROR(symbol, symbol, "LD operator requires an operand."); - il_default_variable_type = il_operand_type; - return NULL; -} - -// SYM_REF0(LDN_operator_c) -void *visit_expression_type_c::visit(LDN_operator_c *symbol) { - if(il_operand_type == NULL) - STAGE3_ERROR(symbol, symbol, "LDN operator requires an operand."); - if(!is_ANY_BIT_compatible(il_operand_type)) - STAGE3_ERROR(symbol, il_operand, "invalid data type of LDN operand, should be of type ANY_BIT."); - il_default_variable_type = il_operand_type; - return NULL; -} - -// SYM_REF0(ST_operator_c) -void *visit_expression_type_c::visit(ST_operator_c *symbol) { - verify_null(symbol); - - if(!is_valid_assignment(il_operand_type, il_default_variable_type)) - STAGE3_ERROR(symbol, symbol, "Type mismatch in ST operation."); - /* TODO: check whether il_operand_type is an LVALUE !! */ - /* data type of il_default_variable_type is unchanged... */ - // il_default_variable_type = il_default_variable_type; - return NULL; -} - -// SYM_REF0(STN_operator_c) - void *visit_expression_type_c::visit(STN_operator_c *symbol) { - verify_null(symbol); - if(!is_valid_assignment(il_operand_type, il_default_variable_type)) - STAGE3_ERROR(symbol, symbol, "Type mismatch in ST operation."); - /* TODO: check whether il_operand_type is an LVALUE !! */ - if(!is_ANY_BIT_compatible(il_default_variable_type)) - STAGE3_ERROR(symbol, symbol, "invalid data type of il_default_variable for STN operand, should be of type ANY_BIT."); - if(!is_ANY_BIT_compatible(il_operand_type)) - STAGE3_ERROR(symbol, il_operand, "invalid data type of STN operand, should be of type ANY_BIT."); - /* data type of il_default_variable_type is unchanged... */ - // il_default_variable_type = il_default_variable_type; - return NULL; -} - -//SYM_REF0(NOT_operator_c) -void *visit_expression_type_c::visit(NOT_operator_c *symbol) { - if(il_operand_type != NULL){ - STAGE3_ERROR(symbol, il_operand, "NOT operator may not have an operand."); - return NULL; - } - if(il_default_variable_type == NULL) { - STAGE3_ERROR(symbol, symbol, "Il default variable should not be NULL."); - return NULL; - } - if(!is_ANY_BIT_compatible(il_default_variable_type)) { - STAGE3_ERROR(symbol, symbol, "Il default variable should be of type ANY_BIT."); - return NULL; - } - /* data type of il_default_variable_type is unchanged... */ - // il_default_variable_type = il_default_variable_type; - return NULL; -} - -// SYM_REF0(S_operator_c) -void *visit_expression_type_c::visit(S_operator_c *symbol) { - verify_null(symbol); - if (!is_BOOL_type(il_default_variable_type)) {STAGE3_ERROR(symbol, symbol, "IL default variable should be BOOL type.");} - if (!is_BOOL_type(il_operand_type)) {STAGE3_ERROR(symbol, il_operand, "operator S requires operand of type BOOL.");} - /* TODO: check whether il_operand_type is an LVALUE !! */ - /* data type of il_default_variable_type is unchanged... */ - // il_default_variable_type = il_default_variable_type; - return NULL; -} - -// SYM_REF0(R_operator_c) -void *visit_expression_type_c::visit(R_operator_c *symbol) { - verify_null(symbol); - if (!is_BOOL_type(il_default_variable_type)) {STAGE3_ERROR(symbol, symbol, "IL default variable should be BOOL type.");} - if (!is_BOOL_type(il_operand_type)) {STAGE3_ERROR(symbol, il_operand, "operator R requires operand of type BOOL.");} - /* TODO: check whether il_operand_type is an LVALUE !! */ - /* data type of il_default_variable_type is unchanged... */ - // il_default_variable_type = il_default_variable_type; - return NULL; -} - - -// SYM_REF0(S1_operator_c) -void *visit_expression_type_c::visit(S1_operator_c *symbol){ - check_il_fbcall(symbol, "S1"); - return NULL; -} - -// SYM_REF0(R1_operator_c) -void *visit_expression_type_c::visit(R1_operator_c *symbol) { - check_il_fbcall(symbol, "R1"); - return NULL; -} - -// SYM_REF0(CLK_operator_c) -void *visit_expression_type_c::visit(CLK_operator_c *symbol) { - check_il_fbcall(symbol, "CLK"); - return NULL; -} - -// SYM_REF0(CU_operator_c) -void *visit_expression_type_c::visit(CU_operator_c *symbol) { - check_il_fbcall(symbol, "CU"); - return NULL; -} - -// SYM_REF0(CD_operator_c) -void *visit_expression_type_c::visit(CD_operator_c *symbol) { - check_il_fbcall(symbol, "CD"); - return NULL; -} - -// SYM_REF0(PV_operator_c) -void *visit_expression_type_c::visit(PV_operator_c *symbol) { - check_il_fbcall(symbol, "PV"); - return NULL; -} - -// SYM_REF0(IN_operator_c) -void *visit_expression_type_c::visit(IN_operator_c *symbol) { - check_il_fbcall(symbol, "IN"); - return NULL; -} - -// SYM_REF0(PT_operator_c) -void *visit_expression_type_c::visit(PT_operator_c *symbol) { - check_il_fbcall(symbol, "PT"); - return NULL; -} - -//SYM_REF0(AND_operator_c) -void *visit_expression_type_c::visit(AND_operator_c *symbol) { - verify_null(symbol); - il_default_variable_type = compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_BIT_compatible, - symbol , il_operand); - return NULL; -} - -//SYM_REF0(OR_operator_c) -void *visit_expression_type_c::visit(OR_operator_c *symbol) { - verify_null(symbol); - il_default_variable_type = compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_BIT_compatible, - symbol , il_operand); - return NULL; -} - -//SYM_REF0(XOR_operator_c) -void *visit_expression_type_c::visit(XOR_operator_c *symbol) { - verify_null(symbol); - il_default_variable_type = compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_BIT_compatible, - symbol , il_operand); - return NULL; -} - -// SYM_REF0(ANDN_operator_c) -void *visit_expression_type_c::visit(ANDN_operator_c *symbol) { - verify_null(symbol); - il_default_variable_type = compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_BIT_compatible, - symbol , il_operand); - return NULL; -} - -// SYM_REF0(ORN_operator_c) -void *visit_expression_type_c::visit(ORN_operator_c *symbol) { - verify_null(symbol); - il_default_variable_type = compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_BIT_compatible, - symbol , il_operand); - return NULL; -} - -// SYM_REF0(XORN_operator_c) -void *visit_expression_type_c::visit(XORN_operator_c *symbol) { - verify_null(symbol); - il_default_variable_type = compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_BIT_compatible, - symbol , il_operand); - return NULL; -} - -// SYM_REF0(ADD_operator_c) -void *visit_expression_type_c::visit(ADD_operator_c *symbol) { - verify_null(symbol); - symbol_c *left_type = il_default_variable_type; - symbol_c *right_type = il_operand_type; - -/* The following is not required, it is already handled by compute_expression() ... */ -/* - if (is_type(left_type, time_type_name_c) && is_type(right_type, time_type_name_c)) - il_default_variable_type = &time_type_name; -*/ - - if (is_type(left_type, tod_type_name_c) && is_type(right_type, time_type_name_c)) - il_default_variable_type = &tod_type_name; - else if (is_type(left_type, safetod_type_name_c) && is_type(right_type, time_type_name_c)) - il_default_variable_type = &tod_type_name; - else if (is_type(left_type, tod_type_name_c) && is_type(right_type, safetime_type_name_c)) - il_default_variable_type = &tod_type_name; - else if (is_type(left_type, safetod_type_name_c) && is_type(right_type, safetime_type_name_c)) - il_default_variable_type = &safetod_type_name; - - else if (is_type(left_type, dt_type_name_c) && is_type(right_type, time_type_name_c)) - il_default_variable_type = &dt_type_name; - else if (is_type(left_type, safedt_type_name_c) && is_type(right_type, time_type_name_c)) - il_default_variable_type = &dt_type_name; - else if (is_type(left_type, dt_type_name_c) && is_type(right_type, safetime_type_name_c)) - il_default_variable_type = &dt_type_name; - else if (is_type(left_type, safedt_type_name_c) && is_type(right_type, safetime_type_name_c)) - il_default_variable_type = &safedt_type_name; - - else il_default_variable_type = compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_MAGNITUDE_compatible, - symbol , il_operand); - return NULL; -} - -// SYM_REF0(SUB_operator_c) -void *visit_expression_type_c::visit(SUB_operator_c *symbol) { - verify_null(symbol); - symbol_c *left_type = il_default_variable_type; - symbol_c *right_type = il_operand_type;; - -/* The following is not required, it is already handled by compute_expression() ... */ -/* - if (typeid(*left_type) == typeid(time_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) - il_default_variable_type = &time_type_name; -*/ - - if (is_type(left_type, tod_type_name_c) && is_type(right_type, time_type_name_c)) - il_default_variable_type = &tod_type_name; - else if (is_type(left_type, safetod_type_name_c) && is_type(right_type, time_type_name_c)) - il_default_variable_type = &tod_type_name; - else if (is_type(left_type, tod_type_name_c) && is_type(right_type, safetime_type_name_c)) - il_default_variable_type = &tod_type_name; - else if (is_type(left_type, safetod_type_name_c) && is_type(right_type, safetime_type_name_c)) - il_default_variable_type = &safetod_type_name; - - else if (is_type(left_type, dt_type_name_c) && is_type(right_type, time_type_name_c)) - il_default_variable_type = &dt_type_name; - else if (is_type(left_type, safedt_type_name_c) && is_type(right_type, time_type_name_c)) - il_default_variable_type = &dt_type_name; - else if (is_type(left_type, dt_type_name_c) && is_type(right_type, safetime_type_name_c)) - il_default_variable_type = &dt_type_name; - else if (is_type(left_type, safedt_type_name_c) && is_type(right_type, safetime_type_name_c)) - il_default_variable_type = &safedt_type_name; - - else if (is_type(left_type, date_type_name_c) && is_type(right_type, date_type_name_c)) - il_default_variable_type = &time_type_name; - else if (is_type(left_type, safedate_type_name_c) && is_type(right_type, date_type_name_c)) - il_default_variable_type = &time_type_name; - else if (is_type(left_type, date_type_name_c) && is_type(right_type, safedate_type_name_c)) - il_default_variable_type = &time_type_name; - else if (is_type(left_type, safedate_type_name_c) && is_type(right_type, safedate_type_name_c)) - il_default_variable_type = &safetime_type_name; - - else if (is_type(left_type, tod_type_name_c) && is_type(right_type, tod_type_name_c)) - il_default_variable_type = &time_type_name; - else if (is_type(left_type, safetod_type_name_c) && is_type(right_type, tod_type_name_c)) - il_default_variable_type = &time_type_name; - else if (is_type(left_type, tod_type_name_c) && is_type(right_type, safetod_type_name_c)) - il_default_variable_type = &time_type_name; - else if (is_type(left_type, safetod_type_name_c) && is_type(right_type, safetod_type_name_c)) - il_default_variable_type = &safetime_type_name; - - else if (is_type(left_type, dt_type_name_c) && is_type(right_type, dt_type_name_c)) - il_default_variable_type = &time_type_name; - else if (is_type(left_type, safedt_type_name_c) && is_type(right_type, dt_type_name_c)) - il_default_variable_type = &time_type_name; - else if (is_type(left_type, dt_type_name_c) && is_type(right_type, safedt_type_name_c)) - il_default_variable_type = &time_type_name; - else if (is_type(left_type, safedt_type_name_c) && is_type(right_type, safedt_type_name_c)) - il_default_variable_type = &safetime_type_name; - - else il_default_variable_type = compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_MAGNITUDE_compatible, - symbol , il_operand); - return NULL; -} - -// SYM_REF0(MUL_operator_c) -void *visit_expression_type_c::visit(MUL_operator_c *symbol) { - verify_null(symbol); - symbol_c *left_type = il_default_variable_type; - symbol_c *right_type = il_operand_type; - - if (is_type(left_type, time_type_name_c) && is_ANY_NUM_compatible(right_type)) - il_default_variable_type = &time_type_name; - else if (is_type(left_type, safetime_type_name_c) && is_ANY_NUM_type(right_type)) - il_default_variable_type = &time_type_name; - else if (is_type(left_type, safetime_type_name_c) && is_ANY_SAFENUM_type(right_type)) - il_default_variable_type = &safetime_type_name; - /* Since we have already checked for ANY_NUM_type and ANY_SAFENUM_type in the previous lines, - * this next line is really only to check for integers/reals of undefined type on 'right_type'... - */ - else if (is_type(left_type, safetime_type_name_c) && is_ANY_NUM_compatible(right_type)) - il_default_variable_type = &safetime_type_name; - - else il_default_variable_type = compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_NUM_compatible, - symbol , il_operand); - return NULL; -} - -// SYM_REF0(DIV_operator_c) -void *visit_expression_type_c::visit(DIV_operator_c *symbol) { - verify_null(symbol); - symbol_c *left_type = il_default_variable_type; - symbol_c *right_type = il_operand_type; - - if (is_type(left_type, time_type_name_c) && is_ANY_NUM_compatible(right_type)) - il_default_variable_type = &time_type_name; - else if (is_type(left_type, safetime_type_name_c) && is_ANY_NUM_type(right_type)) - il_default_variable_type = &time_type_name; - else if (is_type(left_type, safetime_type_name_c) && is_ANY_SAFENUM_type(right_type)) - il_default_variable_type = &safetime_type_name; - /* Since we have already checked for ANY_NUM_type and ANY_SAFENUM_type in the previous lines, - * this next line is really only to check for integers/reals of undefined type on 'right_type'... - */ - else if (is_type(left_type, safetime_type_name_c) && is_ANY_NUM_compatible(right_type)) - il_default_variable_type = &safetime_type_name; - - else il_default_variable_type = compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_NUM_compatible, - symbol , il_operand); - return NULL; -} - -// SYM_REF0(MOD_operator_c) -void *visit_expression_type_c::visit(MOD_operator_c *symbol) { - verify_null(symbol); - il_default_variable_type = compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_INT_compatible, - symbol , il_operand); - return NULL; -} - -// SYM_REF0(GT_operator_c) -void *visit_expression_type_c::visit(GT_operator_c *symbol) { - verify_null(symbol); - compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible, - symbol , il_operand); - il_default_variable_type = &search_expression_type_c::bool_type_name; - return NULL; -} - -//SYM_REF0(GE_operator_c) -void *visit_expression_type_c::visit(GE_operator_c *symbol) { - verify_null(symbol); - compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible, - symbol , il_operand); - il_default_variable_type = &search_expression_type_c::bool_type_name; - return NULL; -} - -//SYM_REF0(EQ_operator_c) -void *visit_expression_type_c::visit(EQ_operator_c *symbol) { - verify_null(symbol); - compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible, - symbol , il_operand); - il_default_variable_type = &search_expression_type_c::bool_type_name; - return NULL; -} - -//SYM_REF0(LT_operator_c) -void *visit_expression_type_c::visit(LT_operator_c *symbol) { - verify_null(symbol); - compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible, - symbol , il_operand); - il_default_variable_type = &search_expression_type_c::bool_type_name; - return NULL; -} - -//SYM_REF0(LE_operator_c) -void *visit_expression_type_c::visit(LE_operator_c *symbol) { - verify_null(symbol); - compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible, - symbol , il_operand); - il_default_variable_type = &search_expression_type_c::bool_type_name; - return NULL; -} - -//SYM_REF0(NE_operator_c) -void *visit_expression_type_c::visit(NE_operator_c *symbol) { - verify_null(symbol); - compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible, - symbol , il_operand); - il_default_variable_type = &search_expression_type_c::bool_type_name; - return NULL; -} - -// SYM_REF0(CAL_operator_c) -void *visit_expression_type_c::visit(CAL_operator_c *symbol) { - return NULL; -} - -// SYM_REF0(CALC_operator_c) -void *visit_expression_type_c::visit(CALC_operator_c *symbol) { - if(il_default_variable_type == NULL) - STAGE3_ERROR(symbol, symbol, "CALC: il default variable should not be NULL."); - if (!is_BOOL_type(il_default_variable_type)) - STAGE3_ERROR(symbol, symbol, "CALC operator requires il_default_variable to be of type BOOL."); - return NULL; -} - -// SYM_REF0(CALCN_operator_c) -void *visit_expression_type_c::visit(CALCN_operator_c *symbol) { - if(il_default_variable_type == NULL) - STAGE3_ERROR(symbol, symbol, "CALCN: il_default_variable should not be NULL."); - if (!is_BOOL_type(il_default_variable_type)) - STAGE3_ERROR(symbol, symbol, "CALCN operator requires il_default_variable to be of type BOOL."); - return NULL; -} - -// SYM_REF0(RET_operator_c) -void *visit_expression_type_c::visit(RET_operator_c *symbol) { - return NULL; -} - -// SYM_REF0(RETC_operator_c) -void *visit_expression_type_c::visit(RETC_operator_c *symbol) { - if(il_default_variable_type == NULL) - STAGE3_ERROR(symbol, symbol, "RETC: il default variable should not be NULL."); - if (!is_BOOL_type(il_default_variable_type)) - STAGE3_ERROR(symbol, symbol, "RETC operator requires il_default_variable to be of type BOOL."); - return NULL; -} - -// SYM_REF0(RETCN_operator_c) -void *visit_expression_type_c::visit(RETCN_operator_c *symbol) { - if(il_default_variable_type == NULL) - STAGE3_ERROR(symbol, symbol, "RETCN: il_default_variable should not be NULL."); - if (!is_BOOL_type(il_default_variable_type)) - STAGE3_ERROR(symbol, symbol, "RETCN operator requires il_default_variable to be of type BOOL."); - return NULL; -} - -// SYM_REF0(JMP_operator_c) -void *visit_expression_type_c::visit(JMP_operator_c *symbol){ - return NULL; -} - -// SYM_REF0(JMPC_operator_c) -void *visit_expression_type_c::visit(JMPC_operator_c *symbol) { - if(il_default_variable_type == NULL) - STAGE3_ERROR(symbol, symbol, "JMPC: il default variable should not be NULL."); - if (!is_BOOL_type(il_default_variable_type)) - STAGE3_ERROR(symbol, symbol, "JMPC operator requires il_default_variable to be of type BOOL."); - return NULL; -} - -// SYM_REF0(JMPCN_operator_c) -void *visit_expression_type_c::visit(JMPCN_operator_c *symbol) { - if(il_default_variable_type == NULL) - STAGE3_ERROR(symbol, symbol, "JMPCN: il_default_variable should not be NULL."); - if (!is_BOOL_type(il_default_variable_type)) - STAGE3_ERROR(symbol, symbol, "JMPCN operator requires il_default_variable to be of type BOOL."); - return NULL; -} - -/* Symbol class handled together with function call checks */ -/* any_identifier ASSIGN */ -// SYM_REF1(il_assign_operator_c, variable_name) -// void *visit_expression_type_c::visit(il_assign_operator_c *symbol, variable_name); - -/* Symbol class handled together with function call checks */ -/*| [NOT] any_identifier SENDTO */ -// SYM_REF2(il_assign_out_operator_c, option, variable_name) -// void *visit_expression_type_c::visit(il_assign_operator_c *symbol, option, variable_name); - - - - - -/***************************************/ -/* B.3 - Language ST (Structured Text) */ -/***************************************/ -/***********************/ -/* B 3.1 - Expressions */ -/***********************/ - -void *visit_expression_type_c::visit(or_expression_c *symbol) { - symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); - symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); - return compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_BIT_compatible, symbol->l_exp, symbol->r_exp); -} - - -void *visit_expression_type_c::visit(xor_expression_c *symbol) { - symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); - symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); - return compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_BIT_compatible, symbol->l_exp, symbol->r_exp); -} - - -void *visit_expression_type_c::visit(and_expression_c *symbol) { - symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); - symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); - return compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_BIT_compatible, symbol->l_exp, symbol->r_exp); -} - - -void *visit_expression_type_c::visit(equ_expression_c *symbol) { - symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); - symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); - compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_ELEMENTARY_OR_ENUMERATED_compatible, symbol->l_exp, symbol->r_exp); - return &search_expression_type_c::bool_type_name; -} - - -void *visit_expression_type_c::visit(notequ_expression_c *symbol) { - symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); - symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); - compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_ELEMENTARY_OR_ENUMERATED_compatible, symbol->l_exp, symbol->r_exp); - return &search_expression_type_c::bool_type_name; -} - - -void *visit_expression_type_c::visit(lt_expression_c *symbol) { - symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); - symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); - compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible, symbol->l_exp, symbol->r_exp); - return &search_expression_type_c::bool_type_name; -} - - -void *visit_expression_type_c::visit(gt_expression_c *symbol) { - symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); - symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); - compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible, symbol->l_exp, symbol->r_exp); - return &search_expression_type_c::bool_type_name; -} - - -void *visit_expression_type_c::visit(le_expression_c *symbol) { - symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); - symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); - compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible, symbol->l_exp, symbol->r_exp); - return &search_expression_type_c::bool_type_name; -} - - -void *visit_expression_type_c::visit(ge_expression_c *symbol) { - symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); - symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); - compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible, symbol->l_exp, symbol->r_exp); - return &search_expression_type_c::bool_type_name; -} - - -void *visit_expression_type_c::visit(add_expression_c *symbol) { - symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); - symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); - -/* The following is already checked in compute_expression */ -/* - if (is_type(left_type, time_type_name_c) && is_type(right_type, time_type_name_c)) - return (void *)&time_type_name; -*/ - - if (is_type(left_type, tod_type_name_c) && is_type(right_type, time_type_name_c)) - return (void *)&tod_type_name; - if (is_type(left_type, safetod_type_name_c) && is_type(right_type, time_type_name_c)) - return (void *)&tod_type_name; - if (is_type(left_type, tod_type_name_c) && is_type(right_type, safetime_type_name_c)) - return (void *)&tod_type_name; - if (is_type(left_type, safetod_type_name_c) && is_type(right_type, safetime_type_name_c)) - return (void *)&safetod_type_name; - - if (is_type(left_type, dt_type_name_c) && is_type(right_type, time_type_name_c)) - return (void *)&dt_type_name; - if (is_type(left_type, safedt_type_name_c) && is_type(right_type, time_type_name_c)) - return (void *)&dt_type_name; - if (is_type(left_type, dt_type_name_c) && is_type(right_type, safetime_type_name_c)) - return (void *)&dt_type_name; - if (is_type(left_type, safedt_type_name_c) && is_type(right_type, safetime_type_name_c)) - return (void *)&safedt_type_name; - - return compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_MAGNITUDE_compatible, symbol->l_exp, symbol->r_exp); -} - - -void *visit_expression_type_c::visit(sub_expression_c *symbol) { - symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); - symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); - -/* The following is already checked in compute_expression */ -/* - if (is_type(left_type, time_type_name_c) && is_type(right_type, time_type_name_c)) - return (void *)&time_type_name; -*/ - - if (is_type(left_type, tod_type_name_c) && is_type(right_type, time_type_name_c)) - return (void *)&tod_type_name; - if (is_type(left_type, safetod_type_name_c) && is_type(right_type, time_type_name_c)) - return (void *)&tod_type_name; - if (is_type(left_type, tod_type_name_c) && is_type(right_type, safetime_type_name_c)) - return (void *)&tod_type_name; - if (is_type(left_type, safetod_type_name_c) && is_type(right_type, safetime_type_name_c)) - return (void *)&safetod_type_name; - - if (is_type(left_type, dt_type_name_c) && is_type(right_type, time_type_name_c)) - return (void *)&dt_type_name; - if (is_type(left_type, safedt_type_name_c) && is_type(right_type, time_type_name_c)) - return (void *)&dt_type_name; - if (is_type(left_type, dt_type_name_c) && is_type(right_type, safetime_type_name_c)) - return (void *)&dt_type_name; - if (is_type(left_type, safedt_type_name_c) && is_type(right_type, safetime_type_name_c)) - return (void *)&safedt_type_name; - - if (is_type(left_type, tod_type_name_c) && is_type(right_type, tod_type_name_c)) - return (void *)&time_type_name; - if (is_type(left_type, safetod_type_name_c) && is_type(right_type, tod_type_name_c)) - return (void *)&time_type_name; - if (is_type(left_type, tod_type_name_c) && is_type(right_type, safetod_type_name_c)) - return (void *)&time_type_name; - if (is_type(left_type, safetod_type_name_c) && is_type(right_type, safetod_type_name_c)) - return (void *)&safetime_type_name; - - if (is_type(left_type, date_type_name_c) && is_type(right_type, date_type_name_c)) - return (void *)&time_type_name; - if (is_type(left_type, safedate_type_name_c) && is_type(right_type, date_type_name_c)) - return (void *)&time_type_name; - if (is_type(left_type, date_type_name_c) && is_type(right_type, safedate_type_name_c)) - return (void *)&time_type_name; - if (is_type(left_type, safedate_type_name_c) && is_type(right_type, safedate_type_name_c)) - return (void *)&safetime_type_name; - - if (is_type(left_type, dt_type_name_c) && is_type(right_type, dt_type_name_c)) - return (void *)&time_type_name; - if (is_type(left_type, safedt_type_name_c) && is_type(right_type, dt_type_name_c)) - return (void *)&time_type_name; - if (is_type(left_type, dt_type_name_c) && is_type(right_type, safedt_type_name_c)) - return (void *)&time_type_name; - if (is_type(left_type, safedt_type_name_c) && is_type(right_type, safedt_type_name_c)) - return (void *)&safetime_type_name; - - return compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_MAGNITUDE_compatible, symbol->l_exp, symbol->r_exp); -} - - -void *visit_expression_type_c::visit(mul_expression_c *symbol) { - symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); - symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); - - if (is_type(left_type, time_type_name_c) && is_ANY_NUM_compatible(right_type)) - return (void *)&time_type_name; - if (is_type(left_type, safetime_type_name_c) && is_ANY_NUM_type(right_type)) - return (void *)&time_type_name; - if (is_type(left_type, safetime_type_name_c) && is_ANY_SAFENUM_type(right_type)) - return (void *)&safetime_type_name; - /* Since we have already checked for ANY_NUM_type and ANY_SAFENUM_type in the previous lines, - * this next line is really only to check for integers/reals of undefined type on 'right_type'... - */ - if (is_type(left_type, safetime_type_name_c) && is_ANY_NUM_compatible(right_type)) - return (void *)&safetime_type_name; - - return compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_NUM_compatible, symbol->l_exp, symbol->r_exp); -} - - -void *visit_expression_type_c::visit(div_expression_c *symbol) { - symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); - symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); - - if (is_type(left_type, time_type_name_c) && is_ANY_NUM_compatible(right_type)) - return (void *)&time_type_name; - if (is_type(left_type, safetime_type_name_c) && is_ANY_NUM_type(right_type)) - return (void *)&time_type_name; - if (is_type(left_type, safetime_type_name_c) && is_ANY_SAFENUM_type(right_type)) - return (void *)&safetime_type_name; - /* Since we have already checked for ANY_NUM_type and ANY_SAFENUM_type in the previous lines, - * this next line is really only to check for integers/reals of undefined type on 'right_type'... - */ - if (is_type(left_type, safetime_type_name_c) && is_ANY_NUM_compatible(right_type)) - return (void *)&safetime_type_name; - - return compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_NUM_compatible, symbol->l_exp, symbol->r_exp); -} - - -void *visit_expression_type_c::visit(mod_expression_c *symbol) { - symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); - symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); - return compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_INT_compatible, symbol->l_exp, symbol->r_exp); -} - - -void *visit_expression_type_c::visit(power_expression_c *symbol) { - symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); - symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); - if (!is_ANY_REAL_compatible(left_type)) - STAGE3_ERROR(symbol->l_exp, symbol->l_exp, "first operand of ** operator has invalid data type, should be of type ANY_REAL."); - if (!is_ANY_NUM_compatible(right_type)) - STAGE3_ERROR(symbol->r_exp, symbol->r_exp, "second operand of ** operator has invalid data type, should be of type ANY_NUM."); - - return (void *)left_type; -} - - -void *visit_expression_type_c::visit(neg_expression_c *symbol) { - symbol_c *exp_type = base_type((symbol_c *)symbol->exp->accept(*this)); - if (!is_ANY_MAGNITUDE_compatible(exp_type)) - STAGE3_ERROR(symbol, symbol, "operand of negate expression '-' has invalid data type, should be of type ANY_MAGNITUDE."); - - return exp_type; -} - - -void *visit_expression_type_c::visit(not_expression_c *symbol) { - symbol_c *type = base_type((symbol_c *)symbol->exp->accept(*this)); - return compute_expression(type, type, &visit_expression_type_c::is_ANY_BIT_compatible, NULL, symbol->exp); -} - - -void *visit_expression_type_c::visit(function_invocation_c *symbol) { - function_symtable_t::iterator lower = function_symtable.lower_bound(symbol->function_name); - function_symtable_t::iterator upper = function_symtable.upper_bound(symbol->function_name); - if (lower == function_symtable.end()) ERROR; - - function_symtable_t::iterator second = lower; - second++; - if (second == upper) { - /* call to a function that is not overloaded. */ - /* now check the semantics of the function call... */ - /* If the syntax parser is working correctly, exactly one of the - * following two symbols will be NULL, while the other is != NULL. - */ - function_declaration_c *f_decl = function_symtable.get_value(lower); - if (symbol-> formal_param_list != NULL) check_formal_call (symbol, f_decl); - if (symbol->nonformal_param_list != NULL) check_nonformal_call(symbol, f_decl); - /* Store the pointer to the declaration of the function being called. - * This data will be used by stage 4 to call the correct function. - * Mostly needed to disambiguate overloaded functions... - * See comments in absyntax.def for more details - */ - symbol->called_function_declaration = f_decl; - return base_type(f_decl->type_name); - } - - /* This is a call to an overloaded function... */ - if (debug) printf("visit_expression_type_c::visit(function_invocation_c *symbol): FOUND CALL TO OVERLOADED FUNCTION!!\n"); - for(; lower != upper; lower++) { - if (debug) printf("visit_expression_type_c::visit(function_invocation_c *symbol): FOUND CALL TO OVERLOADED FUNCTION!! iterating...\n"); - int error_count = 0; - function_declaration_c *f_decl = function_symtable.get_value(lower); - if (symbol-> formal_param_list != NULL) check_formal_call (symbol, f_decl, &error_count); - if (symbol->nonformal_param_list != NULL) check_nonformal_call(symbol, f_decl, false, &error_count); - if (0 == error_count) { - /* Store the pointer to the declaration of the function being called. - * This data will be used by stage 4 to call the correct function. - * Mostly needed to disambiguate overloaded functions... - * See comments in absyntax.def for more details - */ - symbol->called_function_declaration = f_decl; - return base_type(f_decl->type_name); - } - } - - /* No compatible function was found for this function call */ - STAGE3_ERROR(symbol, symbol, "Call to an overloaded function with invalid parameter type."); - return NULL; -} - -/********************/ -/* B 3.2 Statements */ -/********************/ -// SYM_LIST(statement_list_c) -/* The visitor of the base class search_visitor_c will handle calling each instruction in the list. - * We do not need to do anything here... - */ -// void *visit_expression_type_c::visit(statement_list_c *symbol) - - -/*********************************/ -/* B 3.2.1 Assignment Statements */ -/*********************************/ - -void *visit_expression_type_c::visit(assignment_statement_c *symbol) { - symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); - symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); - - if (debug) { - printf("visit_expression_type_c::visit(assignment_statement_c) called. Checking --->"); - symbolic_variable_c *hi = dynamic_cast(symbol->l_exp); - if (hi != NULL) { - identifier_c *hi1 = dynamic_cast(hi->var_name); - if (hi1 != NULL) printf("%s", hi1->value); - } - printf(" := "); - hex_integer_c *hi2 = dynamic_cast(symbol->r_exp); - if (hi2 != NULL) printf("%s", hi2->value); - printf("\n"); - } // if (debug) - - if (NULL == left_type) { - STAGE3_ERROR(symbol->l_exp, symbol->l_exp, "Could not determine data type of expression (undefined variable, constant, or structure element?).\n"); - } else if (NULL == right_type) { - STAGE3_ERROR(symbol->r_exp, symbol->r_exp, "Could not determine data type of expression (undefined variable, constant, or structure element?).\n"); - } else if (!is_valid_assignment(left_type, right_type)) - STAGE3_ERROR(symbol, symbol, "data type mismatch in assignment statement!\n"); - - return NULL; -} - - - -/*****************************************/ -/* B 3.2.2 Subprogram Control Statements */ -/*****************************************/ - -/* RETURN */ -// SYM_REF0(return_statement_c) - - -/* fb_name '(' [param_assignment_list] ')' */ -/* param_assignment_list -> may be NULL ! */ -// SYM_REF3(fb_invocation_c, fb_name, formal_param_list, nonformal_param_list) -void *visit_expression_type_c::visit(fb_invocation_c *symbol) { - symbol_c *fb_decl = search_varfb_instance_type->get_basetype_decl(symbol->fb_name); - /* The following should never occur. The function block must be defined, - * and the FB type being called MUST be in the symtable... - * This was all already checked at stage 2! - */ - if (NULL == fb_decl) ERROR; - - /* now check the semantics of the fb call... */ - /* If the syntax parser is working correctly, exactly one of the - * following two symbols will be NULL, while the other is != NULL. - */ - if (symbol-> formal_param_list != NULL) check_formal_call (symbol, fb_decl); - if (symbol->nonformal_param_list != NULL) check_nonformal_call(symbol, fb_decl); - - return NULL; -} - - -#if 0 -/* helper symbol for fb_invocation */ -/* param_assignment_list ',' param_assignment */ -SYM_LIST(param_assignment_list_c) - -/* variable_name ASSIGN expression */ -SYM_REF2(input_variable_param_assignment_c, variable_name, expression) - -/* [NOT] variable_name '=>' variable */ -SYM_REF3(output_variable_param_assignment_c, not_param, variable_name, variable) - -/* helper CLASS for output_variable_param_assignment */ -SYM_REF0(not_paramassign_c) -#endif - -/********************************/ -/* B 3.2.3 Selection Statements */ -/********************************/ - -/* IF expression THEN statement_list elseif_statement_list ELSE statement_list END_IF */ -// SYM_REF4(if_statement_c, expression, statement_list, elseif_statement_list, else_statement_list) -void *visit_expression_type_c::visit(if_statement_c *symbol) { - symbol_c *expr_type = base_type((symbol_c*)symbol->expression->accept(*this)); - if (!is_BOOL_type(expr_type)) STAGE3_ERROR(symbol->expression,symbol->expression,"IF conditional expression is not of boolean type."); - if (NULL != symbol->statement_list) - symbol->statement_list->accept(*this); - if (NULL != symbol->elseif_statement_list) - symbol->elseif_statement_list->accept(*this); - if (NULL != symbol->else_statement_list) - symbol->else_statement_list->accept(*this); - return NULL; -} - -/* helper symbol for if_statement */ -// SYM_LIST(elseif_statement_list_c) -// void *visit_expression_type_c::visit(elseif_statement_list_c *symbol) { } - -/* helper symbol for elseif_statement_list */ -/* ELSIF expression THEN statement_list */ -// SYM_REF2(elseif_statement_c, expression, statement_list) -void *visit_expression_type_c::visit(elseif_statement_c *symbol) { - symbol_c *elseif_expr_type = base_type((symbol_c*)symbol->expression->accept(*this)); - if(!is_BOOL_type(elseif_expr_type)) STAGE3_ERROR(symbol->expression,symbol->expression,"ELSIF conditional expression is not of boolean type."); - if (NULL != symbol->statement_list) - symbol->statement_list->accept(*this); - return NULL; -} - - -/* CASE expression OF case_element_list ELSE statement_list END_CASE */ -// SYM_REF3(case_statement_c, expression, case_element_list, statement_list) -void *visit_expression_type_c::visit(case_statement_c *symbol) { - case_expression_type = base_type((symbol_c*)symbol->expression->accept(*this)); - if (NULL != case_expression_type) { - if (NULL != symbol->case_element_list) - symbol->case_element_list->accept(*this); - } - if (NULL != symbol->statement_list) - symbol->statement_list->accept(*this); - return NULL; -} - -#if 0 -/* helper symbol for case_statement */ -// SYM_LIST(case_element_list_c) -// void *visit_expression_type_c::visit(case_element_list_c *symbol); - -/* case_list ':' statement_list */ -// SYM_REF2(case_element_c, case_list, statement_list) -void *visit_expression_type_c::visit(case_element_c *symbol); -#endif - -// SYM_LIST(case_list_c) -void *visit_expression_type_c::visit(case_list_c *symbol) { - symbol_c *element_type; - for(int i = 0; i < symbol->n; i++) { - element_type = (symbol_c *)symbol->elements[i]->accept(*this); - if (NULL == element_type) { - STAGE3_ERROR(symbol->elements[i], symbol->elements[i], "Case list element has undefined data type."); - } else { - element_type = base_type(element_type); - if (NULL != element_type){ - /* The CASE value is only used for comparison (and not assingment), so we only check for compatibility! */ - if (!is_compatible_type(case_expression_type, element_type)) - STAGE3_ERROR(symbol->elements[i], symbol->elements[i], "Invalid data type of case list element."); - } - } - } - return NULL; -} - -/********************************/ -/* B 3.2.4 Iteration Statements */ -/********************************/ - -/* FOR control_variable ASSIGN expression TO expression [BY expression] DO statement_list END_FOR */ -// SYM_REF5(for_statement_c, control_variable, beg_expression, end_expression, by_expression, statement_list) -void *visit_expression_type_c::visit(for_statement_c *symbol) { - symbol_c *var_type = (symbol_c*)symbol->control_variable->accept(*this); - if (NULL == var_type) ERROR; - var_type = base_type(var_type); - if (NULL == var_type) ERROR; - // ASSIGN - symbol_c *beg_expr_type = base_type((symbol_c*)symbol->beg_expression->accept(*this)); - if (NULL != beg_expr_type) { - /* The BEG value is assigned to the variable, so we check for assignment validity! */ - if(!is_valid_assignment(var_type, beg_expr_type)) - STAGE3_ERROR(symbol->beg_expression, symbol->beg_expression, "Data type mismatch between control variable and initial value."); - } - // TO - symbol_c *end_expr_type = base_type((symbol_c*)symbol->end_expression->accept(*this)); - if (NULL != end_expr_type) { - /* The TO value is only used for comparison, so we only check for compatibility! */ - if(!is_compatible_type(var_type, end_expr_type)) - STAGE3_ERROR(symbol->end_expression, symbol->end_expression, "Data type mismatch between control variable and final value."); - } - // BY - if(symbol->by_expression != NULL) { - symbol_c *by_expr_type = base_type((symbol_c*)symbol->by_expression->accept(*this)); - if (NULL != end_expr_type) { - /* The BY value is used in an expression (add, sub, ...), so we only check for compatibility! */ - if(!is_compatible_type(var_type, by_expr_type)) - STAGE3_ERROR(symbol->by_expression, symbol->by_expression, "Data type mismatch between control variable and BY value."); - } - } - // DO - if (NULL != symbol->statement_list) - symbol->statement_list->accept(*this); - return NULL; -} - - -/* WHILE expression DO statement_list END_WHILE */ -// SYM_REF2(while_statement_c, expression, statement_list) -void *visit_expression_type_c::visit(while_statement_c *symbol) { - symbol_c *expr_type = base_type((symbol_c*)symbol->expression->accept(*this)); - if (NULL != expr_type) { - if(!is_BOOL_type(expr_type)) - STAGE3_ERROR(symbol->expression,symbol->expression,"WHILE conditional expression is not of boolean type."); - } - - if (NULL != symbol->statement_list) - symbol->statement_list->accept(*this); - return NULL; -} - -/* REPEAT statement_list UNTIL expression END_REPEAT */ -// SYM_REF2(repeat_statement_c, statement_list, expression) -void *visit_expression_type_c::visit(repeat_statement_c *symbol) { - if (NULL != symbol->statement_list) - symbol->statement_list->accept(*this); - - symbol_c *expr_type = base_type((symbol_c*)symbol->expression->accept(*this)); - if (NULL != expr_type) { - if(!is_BOOL_type(expr_type)) - STAGE3_ERROR(symbol->expression,symbol->expression,"REPEAT conditional expression is not of boolean type."); - } - return NULL; -} - -/* EXIT */ -// SYM_REF0(exit_statement_c) - - - diff -r 0c2ef191b22a -r d48f53715f77 stage3/visit_expression_type.hh --- a/stage3/visit_expression_type.hh Wed Feb 01 13:01:08 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,389 +0,0 @@ -/* - * matiec - a compiler for the programming languages defined in IEC 61131-3 - * - * Copyright (C) 2009-2011 Mario de Sousa (msousa@fe.up.pt) - * Copyright (C) 2007-2011 Laurent Bessard and Edouard Tisserant - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * - * This code is made available on the understanding that it will not be - * used in safety-critical situations without a full and competent review. - */ - -/* - * An IEC 61131-3 compiler. - * - * Based on the - * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10) - * - */ - -/* Verify whether the semantic rules of data type compatibility are being followed. - * - * For example: - */ - -#include "../absyntax_utils/absyntax_utils.hh" - -class visit_expression_type_c: public search_constant_type_c { - - private: - search_varfb_instance_type_c *search_varfb_instance_type; - search_base_type_c search_base_type; - - /* When calling a function block, we must first find it's type, - * by searching through the declarations of the variables currently - * in scope. - * This class does just that... - * A new bject instance is instantiated whenever we start checking semantics - * for a function block type declaration, or a program declaration. - * This object instance will then later be called while the - * function block's or the program's body is being handled. - * - * Note that functions cannot contain calls to function blocks, - * so we do not create an object instance when handling - * a function declaration. - */ -// search_var_instance_decl_c *search_var_instance_decl; - - /* This variable was created to pass information from - * visit_expression_type_c::visit(case_statement_c *symbol) function to - * visit_expression_type_c::visit(case_list_c *symbol) function. - */ - symbol_c *case_expression_type; - - /* In IL code, once we find a type mismatch error, it is best to - * ignore any further errors until the end of the logicl operation, - * i.e. until the next LD. - * However, we cannot clear the il_error flag on all LD operations, - * as these may also be used within parenthesis. LD operations - * within parenthesis may not clear the error flag. - * We therefore need a counter to know how deep inside a parenthesis - * structure we are. - */ - int il_parenthesis_level; - bool il_error; - bool error_found; - - /* the current data type of the data stored in the IL stack, i.e. the default variable */ - symbol_c *il_default_variable_type; - /* the current IL operand being analysed - its symbol and its data type */ - symbol_c *il_operand_type; - symbol_c *il_operand; - - - public: - visit_expression_type_c(symbol_c *ignore); - virtual ~visit_expression_type_c(void); - - bool get_error_found(void); - - typedef struct { - symbol_c *value; - symbol_c *type; - } value_and_type_t; - - /* A helper function... */ - bool is_ANY_ELEMENTARY_type (symbol_c *type_symbol); - bool is_ANY_SAFEELEMENTARY_type (symbol_c *type_symbol); - bool is_ANY_ELEMENTARY_compatible (symbol_c *type_symbol); - - bool is_ANY_MAGNITUDE_type (symbol_c *type_symbol); - bool is_ANY_SAFEMAGNITUDE_type (symbol_c *type_symbol); - bool is_ANY_MAGNITUDE_compatible (symbol_c *type_symbol); - - bool is_ANY_DATE_type (symbol_c *type_symbol); - bool is_ANY_SAFEDATE_type (symbol_c *type_symbol); - bool is_ANY_DATE_compatible (symbol_c *type_symbol); - - bool is_ANY_STRING_type (symbol_c *type_symbol); - bool is_ANY_SAFESTRING_type (symbol_c *type_symbol); - bool is_ANY_STRING_compatible (symbol_c *type_symbol); - - bool is_ANY_INT_type (symbol_c *type_symbol); - bool is_ANY_SAFEINT_type (symbol_c *type_symbol); - bool is_ANY_INT_compatible (symbol_c *type_symbol); - - bool is_ANY_REAL_type (symbol_c *type_symbol); - bool is_ANY_SAFEREAL_type (symbol_c *type_symbol); - bool is_ANY_REAL_compatible (symbol_c *type_symbol); - - bool is_ANY_NUM_type (symbol_c *type_symbol); - bool is_ANY_SAFENUM_type (symbol_c *type_symbol); - bool is_ANY_NUM_compatible (symbol_c *type_symbol); - - bool is_ANY_BIT_type (symbol_c *type_symbol); - bool is_ANY_SAFEBIT_type (symbol_c *type_symbol); - bool is_ANY_BIT_compatible (symbol_c *type_symbol); - - bool is_BOOL_type (symbol_c *type_symbol); - bool is_SAFEBOOL_type (symbol_c *type_symbol); - bool is_ANY_BOOL_compatible (symbol_c *type_symbol); - - bool is_nonneg_literal_integer_type (symbol_c *type_symbol); - bool is_literal_integer_type (symbol_c *type_symbol); - bool is_literal_real_type (symbol_c *type_symbol); - bool is_literal_bool_type (symbol_c *type_symbol); - - bool is_ANY_ELEMENTARY_OR_ENUMERATED_compatible (symbol_c *type_symbol); - - /* Determine the common data type between two data types. - * If no common data type found, return NULL. - * - * If data types are identical, return the first (any would do...). - * If any of the datat types is a literal, we confirm that - * the literal uses less bits than the fixed size data type. - * e.g. BYTE and 1024 returns NULL - * BYTE and 255 returns BYTE - * - * If two literals, then return the literal that requires more bits... - */ - symbol_c *common_type__(symbol_c *first_type, symbol_c *second_type); - /* Determine the common data type between two data types. - * Unlike the common_type__() function, we stop the compiler with an ERROR - * if no common data type is found. - */ - symbol_c *common_type(symbol_c *first_type, symbol_c *second_type); -/* Return TRUE if the second (value) data type may be assigned to a variable of the first (variable) data type - * such as: - * var_type value_type - * BOOL BYTE#7 -> returns false - * INT INT#7 -> returns true - * INT 7 -> returns true - * REAL 7.89 -> returns true - * REAL 7 -> returns true - * INT 7.89 -> returns false - * SAFEBOOL BOOL#1 -> returns false !!! - * etc... - * - * NOTE: It is assumed that the var_type is the data type of an lvalue - */ - bool is_valid_assignment(symbol_c *var_type, symbol_c *value_type); - -/* Return TRUE if there is a common data type, otherwise return FALSE - * i.e., return TRUE if both data types may be used simultaneously in an expression - * such as: - * BOOL#0 AND BYTE#7 -> returns false - * 0 AND BYTE#7 -> returns true - * INT#10 AND INT#7 -> returns true - * INT#10 AND 7 -> returns true - * REAL#34.3 AND 7.89 -> returns true - * REAL#34.3 AND 7 -> returns true - * INT#10 AND 7.89 -> returns false - * SAFEBOOL#0 AND BOOL#1 -> returns true !!! - * etc... - */ - bool is_compatible_type(symbol_c *first_type, symbol_c *second_type); - - /* check semantics of FB call in the IL language using input operators */ - /* e.g. CU, CLK, IN, PT, SR, ... */ - void check_il_fbcall(symbol_c *symbol, const char *input_operator); - /* check the semantics of a FB or Function non-formal call */ - /* e.g. foo(1, 2, 3, 4); */ - /* If error_count pointer is NULL, print out error messages. - * If error_count pointer is != NULL, do not print out error messages, but tally up - * how many errors were found. - */ - void check_nonformal_call(symbol_c *f_call, symbol_c *f_decl, bool use_il_defvar = false, int *error_count = NULL); - /* check the semantics of a FB or Function formal call */ - /* e.g. foo(IN1 := 1, OUT1 =>x, EN := true); */ - /* If error_count pointer is NULL, print out error messages. - * If error_count pointer is != NULL, do not print out error messages, but tally up - * how many errors were found. - */ - void check_formal_call(symbol_c *f_call, symbol_c *f_decl, int *error_count = NULL); - - - void *compute_standard_function_default(function_invocation_c *st_symbol, il_formal_funct_call_c *il_symbol); - void *compute_standard_function_il(il_function_call_c *symbol, symbol_c *param_data_type); - - - /* A helper function... */ - typedef bool (visit_expression_type_c::*is_data_type_t)(symbol_c *type_symbol); /* a pointer to a function! */ -// symbol_c *compute_boolean_expression(symbol_c *left_exp, symbol_c *right_exp, is_data_type_t is_data_type); -// symbol_c *compute_numeric_expression(symbol_c *left_exp, symbol_c *right_exp, is_data_type_t is_data_type); -// symbol_c *compute_expression(symbol_c *left_exp, symbol_c *right_exp, is_data_type_t is_data_type); - symbol_c *compute_expression(symbol_c *left_type, symbol_c *right_type, is_data_type_t is_data_type, - symbol_c *left_expr, symbol_c *right_expr); - - - /* a helper function... */ - symbol_c *base_type(symbol_c *symbol); - - /* a helper function... */ - void *verify_null(symbol_c *symbol); - - /********************************/ - /* B 1.3.3 - Derived data types */ - /********************************/ - void *visit(data_type_declaration_c *symbol); - - /*********************/ - /* B 1.4 - Variables */ - /*********************/ - void *visit(symbolic_variable_c *symbol); - - /********************************************/ - /* B 1.4.1 - Directly Represented Variables */ - /********************************************/ - void *visit(direct_variable_c *symbol); - - /*************************************/ - /* B 1.4.2 - Multi-element variables */ - /*************************************/ - - void *visit(array_variable_c *symbol); - void *visit(structured_variable_c *symbol); - - /********************************/ - /* B 1.7 Configuration elements */ - /********************************/ - void *visit(configuration_declaration_c *symbol); - -/****************************************/ - /* B.2 - Language IL (Instruction List) */ - /****************************************/ - /***********************************/ - /* B 2.1 Instructions and Operands */ - /***********************************/ - // void *visit(instruction_list_c *symbol); - void *visit(il_simple_operation_c *symbol); - void *visit(il_function_call_c *symbol); - void *visit(il_expression_c *symbol); -// void *visit(il_jump_operation_c *symbol); - void *visit(il_fb_call_c *symbol); - void *visit(il_formal_funct_call_c *symbol); - /* - void *visit(il_operand_list_c *symbol); - void *visit(simple_instr_list_c *symbol); - void *visit(il_param_list_c *symbol); - void *visit(il_param_assignment_c *symbol); - void *visit(il_param_out_assignment_c *symbol); - */ - - /*******************/ - /* B 2.2 Operators */ - /*******************/ - void *visit(LD_operator_c *symbol); - void *visit(LDN_operator_c *symbol); - void *visit(ST_operator_c *symbol); - void *visit(STN_operator_c *symbol); - void *visit(NOT_operator_c *symbol); - void *visit(S_operator_c *symbol); - void *visit(R_operator_c *symbol); - void *visit(S1_operator_c *symbol); - void *visit(R1_operator_c *symbol); - void *visit(CLK_operator_c *symbol); - void *visit(CU_operator_c *symbol); - void *visit(CD_operator_c *symbol); - void *visit(PV_operator_c *symbol); - void *visit(IN_operator_c *symbol); - void *visit(PT_operator_c *symbol); - void *visit(AND_operator_c *symbol); - void *visit(OR_operator_c *symbol); - void *visit(XOR_operator_c *symbol); - void *visit(ANDN_operator_c *symbol); - void *visit(ORN_operator_c *symbol); - void *visit(XORN_operator_c *symbol); - void *visit(ADD_operator_c *symbol); - void *visit(SUB_operator_c *symbol); - void *visit(MUL_operator_c *symbol); - void *visit(DIV_operator_c *symbol); - void *visit(MOD_operator_c *symbol); - void *visit(GT_operator_c *symbol); - void *visit(GE_operator_c *symbol); - void *visit(EQ_operator_c *symbol); - void *visit(LT_operator_c *symbol); - void *visit(LE_operator_c *symbol); - void *visit(NE_operator_c *symbol); - void *visit(CAL_operator_c *symbol); - void *visit(CALC_operator_c *symbol); - void *visit(CALCN_operator_c *symbol); - void *visit(RET_operator_c *symbol); - void *visit(RETC_operator_c *symbol); - void *visit(RETCN_operator_c *symbol); - void *visit(JMP_operator_c *symbol); - void *visit(JMPC_operator_c *symbol); - void *visit(JMPCN_operator_c *symbol); - /* Symbol class handled together with function call checks */ - // void *visit(il_assign_operator_c *symbol, variable_name); - /* Symbol class handled together with function call checks */ - // void *visit(il_assign_operator_c *symbol, option, variable_name); - - - - /***************************************/ - /* B.3 - Language ST (Structured Text) */ - /***************************************/ - /***********************/ - /* B 3.1 - Expressions */ - /***********************/ - void *visit(or_expression_c *symbol); - void *visit(xor_expression_c *symbol); - void *visit(and_expression_c *symbol); - void *visit(equ_expression_c *symbol); - void *visit(notequ_expression_c *symbol); - void *visit(lt_expression_c *symbol); - void *visit(gt_expression_c *symbol); - void *visit(le_expression_c *symbol); - void *visit(ge_expression_c *symbol); - void *visit(add_expression_c *symbol); - void *visit(sub_expression_c *symbol); - void *visit(mul_expression_c *symbol); - void *visit(div_expression_c *symbol); - void *visit(mod_expression_c *symbol); - void *visit(power_expression_c *symbol); - void *visit(neg_expression_c *symbol); - void *visit(not_expression_c *symbol); - void *visit(function_invocation_c *symbol); - - /*********************************/ - /* B 3.2.1 Assignment Statements */ - /*********************************/ - void *visit(assignment_statement_c *symbol); - - /*****************************************/ - /* B 3.2.2 Subprogram Control Statements */ - /*****************************************/ - void *visit(fb_invocation_c *symbol); - - /********************************/ - /* B 3.2.3 Selection Statements */ - /********************************/ - - void *visit(if_statement_c *symbol); -// void *visit(elseif_statement_list_c *symbol); - void *visit(elseif_statement_c *symbol); - void *visit(case_statement_c *symbol); -// void *visit(case_element_list_c *symbol); -// void *visit(case_element_c *symbol); - void *visit(case_list_c *symbol); - - /********************************/ - /* B 3.2.4 Iteration Statements */ - /********************************/ - - void *visit(for_statement_c *symbol); - void *visit(while_statement_c *symbol); - void *visit(repeat_statement_c *symbol); - - -//TODO: delete this functions. Why are they needed? -void *visit(program_declaration_c *symbol); -void *visit(function_declaration_c *symbol); -void *visit(function_block_declaration_c *symbol); - -}; // visit_expression_type_c - diff -r 0c2ef191b22a -r d48f53715f77 stage4/generate_c/generate_c.cc --- a/stage4/generate_c/generate_c.cc Wed Feb 01 13:01:08 2012 +0000 +++ b/stage4/generate_c/generate_c.cc Wed Feb 01 19:49:11 2012 +0000 @@ -2224,10 +2224,10 @@ if (var_decl == NULL) ERROR; else - vartype = search_config_instance->get_vartype(); + vartype = search_config_instance->get_vartype(current_var_reference); } else - vartype = search_resource_instance->get_vartype(); + vartype = search_resource_instance->get_vartype(current_var_reference); s4o.print(s4o.indent_spaces + "{extern "); var_decl->accept(*this); @@ -2259,10 +2259,10 @@ if (var_decl == NULL) ERROR; else - vartype = search_config_instance->get_vartype(); + vartype = search_config_instance->get_vartype(current_var_reference); } else - vartype = search_resource_instance->get_vartype(); + vartype = search_resource_instance->get_vartype(current_var_reference); s4o.print(s4o.indent_spaces + "{extern "); var_decl->accept(*this); diff -r 0c2ef191b22a -r d48f53715f77 stage4/generate_c/generate_c_sfc.cc --- a/stage4/generate_c/generate_c_sfc.cc Wed Feb 01 13:01:08 2012 +0000 +++ b/stage4/generate_c/generate_c_sfc.cc Wed Feb 01 19:49:11 2012 +0000 @@ -844,7 +844,7 @@ for(pt = variable_list.begin(); pt != variable_list.end(); pt++) { symbol_c *var_decl = search_var_instance_decl->get_decl(pt->symbol); if (var_decl != NULL) { - unsigned int vartype = search_var_instance_decl->get_vartype(); + unsigned int vartype = search_var_instance_decl->get_vartype(pt->symbol); s4o.print(s4o.indent_spaces); if (vartype == search_var_instance_decl_c::external_vt) diff -r 0c2ef191b22a -r d48f53715f77 stage4/generate_c/generate_c_st.cc --- a/stage4/generate_c/generate_c_st.cc Wed Feb 01 13:01:08 2012 +0000 +++ b/stage4/generate_c/generate_c_st.cc Wed Feb 01 19:49:11 2012 +0000 @@ -342,7 +342,7 @@ case complextype_suffix_vg: symbol->subscripted_variable->accept(*this); - current_array_type = search_varfb_instance_type->get_type_id(symbol->subscripted_variable); + current_array_type = search_varfb_instance_type->get_basetype_decl(symbol->subscripted_variable); if (current_array_type == NULL) ERROR; s4o.print(".table"); @@ -356,7 +356,7 @@ if (this->is_variable_prefix_null()) { symbol->subscripted_variable->accept(*this); - current_array_type = search_varfb_instance_type->get_type_id(symbol->subscripted_variable); + current_array_type = search_varfb_instance_type->get_basetype_decl(symbol->subscripted_variable); if (current_array_type == NULL) ERROR; s4o.print(".table");