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; +}