diff --git a/examples/type-facilities/type-facilities.cpp b/examples/type-facilities/type-facilities.cpp index 26b321c..994ed9f 100644 --- a/examples/type-facilities/type-facilities.cpp +++ b/examples/type-facilities/type-facilities.cpp @@ -1,88 +1,98 @@ /******************************************************************************* * * File: type-facilities.cpp * * Contents: An example showcasing various type-related support facilities. * * Copyright 2017 * * Author: David Juhasz (david.juhasz@tuwien.ac.at) * ******************************************************************************/ #include "rosa/config/version.h" #include "rosa/support/log.h" #include "rosa/support/terminal_colors.h" #include "rosa/support/type_token.hpp" #include using namespace rosa; using namespace rosa::terminal; int main(void) { LOG_INFO_STREAM << library_string() << " -- " << Color::Red << "type facilities" << Color::Default << std::endl; auto &Log = LOG_TRACE_STREAM << std::endl; Log << "NumberOfBuiltinTypes: " << NumberOfBuiltinTypes << std::endl << "TokenBits: " << token::TokenBits << std::endl << "RepresentationBits: " << token::RepresentationBits << std::endl << "MaxTokenizableListSize: " << token::MaxTokenizableListSize << std::endl << std::endl; Log << "Type number information on 'uint8_t':" << std::endl; constexpr TypeNumber TN = TypeNumberOf::Value; Log << " type number: " << PRINTABLE_TN(TN) << std::endl << " size: " << TypeForNumber::Size << std::endl << " name: " << TypeForNumber::Name << std::endl << std::endl; + Log << "Type number information on 'std::string':" << std::endl; + constexpr TypeNumber TNS = TypeNumberOf::Value; + Log << " type number: " << PRINTABLE_TN(TNS) << std::endl + << " size: " << TypeForNumber::Size << std::endl + << " name: " << TypeForNumber::Name << std::endl + << std::endl; + Log << "Type number information of AtomConstants:" << std::endl; using Atom1 = AtomConstant; using Atom2 = AtomConstant; Log << " std::is_same::value: " << std::is_same::value << std::endl << " TypeNumberOf::Value: " << PRINTABLE_TN(TypeNumberOf::Value) << std::endl << " TypeNumberOf::Value: " << PRINTABLE_TN(TypeNumberOf::Value) << std::endl << " name: " << TypeForNumber::Value>::Name << std::endl << std::endl; - Log << "Type token information on 'TypeList':" + Log << "Type token information on 'TypeList':" << std::endl; // Token is generated statically. - constexpr Token T = TypeToken::Value; - STATIC_ASSERT((T == TypeListToken>::Value), - "alias template definition is wrong"); + constexpr Token T = TypeToken::Value; + STATIC_ASSERT( + (T == TypeListToken>::Value), + "alias template definition is wrong"); Token T_ = T; // We need a non-const value for dropping head later. // Iterate over encoded entries in Token. while (!emptyToken(T_)) { Log << " token: " << PRINTABLE_TOKEN(T_) << std::endl << " valid: " << validToken(T_) << std::endl << " empty: " << emptyToken(T_) << std::endl << " length: " << lengthOfToken(T_) << std::endl << " full size: " << sizeOfValuesOfToken(T_) << std::endl << " head type number: " << PRINTABLE_TN(typeNumberOfHeadOfToken(T_)) << std::endl << " size of head: " << sizeOfHeadOfToken(T_) << std::endl << " name of head: " << nameOfHeadOfToken(T_) << std::endl << " is head uint8_t: " << isHeadOfTokenTheSameType(T_) << std::endl << " is head uint16_t: " << isHeadOfTokenTheSameType(T_) << std::endl + << " is head std::string: " + << isHeadOfTokenTheSameType(T_) << std::endl << "Dropping head..." << std::endl; dropHeadOfToken(T_); } // Here when Token became empty. Log << " token: " << PRINTABLE_TOKEN(T_) << std::endl << " empty: " << emptyToken(T_) << std::endl; return 0; } diff --git a/include/rosa/support/squashed_int.hpp b/include/rosa/support/squashed_int.hpp index 94bf918..89afb0d 100644 --- a/include/rosa/support/squashed_int.hpp +++ b/include/rosa/support/squashed_int.hpp @@ -1,69 +1,85 @@ /****************************************************************************** * * File: squashed_int.hpp * * Contents: Facilities for squashing integer types into standard equivalents. * * Copyright 2017 * * Author: David Juhasz (david.juhasz@tuwien.ac.at) * - * This implementation is based on the squashed_int implementation of CAF. + * This implementation is partially based on the squashed_int implementation of + * CAF. * TODO: Check license. * ******************************************************************************/ #ifndef ROSA_SUPPORT_SQUASHED_INT_HPP #define ROSA_SUPPORT_SQUASHED_INT_HPP #include "rosa/support/type_list.hpp" #include "rosa/support/type_pair.hpp" namespace rosa { // Compile-time list of integer types. // NOTE: This list is used to select a proper type as type_nr_t, // always make sure that type_nr_t remains correct whenever changing the list. using IntegerTypesBySize = TypeList< // bytes - unit_t, // 0 + none_t, // 0 TypePair, // 1 TypePair, // 2 - unit_t, // 3 + none_t, // 3 TypePair, // 4 - unit_t, // 5 - unit_t, // 6 - unit_t, // 7 + none_t, // 5 + none_t, // 6 + none_t, // 7 TypePair // 8 >; // Squashes integer types into [u]int_[8|16|32|64]_t equivalents. -template struct SquashedInt { +// STATIC PRE: std::is_integral::value +template struct SquashedInt { + STATIC_ASSERT((std::is_integral::value), "squashing a non-integral type"); using TPair = typename TypeListAt::Type; using Type = typename std::conditional::value, typename TPair::First, typename TPair::Second>::type; }; // Convenience alias for obtaining a squashed int type. -template +template using squashed_int_t = typename SquashedInt::Type; +// Squashes T if T is integral, otherwise uses T. +template ::value> +struct SquashedType { + using Type = T; +}; + +template +struct SquashedType { + using Type = squashed_int_t; +}; + +// Convenience alias for obtaining a squashed type. +template +using squashed_t = typename SquashedType::Type; + // Replaces all integral types with their corresponding squashed integer. template struct SquashedTypeList; template <> struct SquashedTypeList { using Type = EmptyTypeList; }; template struct SquashedTypeList> { - using SquashedT = typename std::conditional::value, - squashed_int_t, T>::type; using Type = typename TypeListPush< - SquashedT, typename SquashedTypeList>::Type>::Type; + squashed_t, typename SquashedTypeList>::Type>::Type; }; } // End namespace rosa #endif // ROSA_SUPPORT_SQUASHED_INT_HPP diff --git a/include/rosa/support/type_numbers.hpp b/include/rosa/support/type_numbers.hpp index 9b06092..7ae359a 100644 --- a/include/rosa/support/type_numbers.hpp +++ b/include/rosa/support/type_numbers.hpp @@ -1,169 +1,162 @@ /****************************************************************************** * * File: type_numbers.hpp * * Contents: Facilities for registering supported types and representing them * with numbers. * * Copyright 2017 * * Author: David Juhasz (david.juhasz@tuwien.ac.at) * * This implementation is partially based on the type_number implementation of * CAF. * TODO: Check license. * ******************************************************************************/ #ifndef ROSA_SUPPORT_TYPE_NUMBERS_HPP #define ROSA_SUPPORT_TYPE_NUMBERS_HPP #include "rosa/support/atom.hpp" #include "rosa/support/math.hpp" #include "rosa/support/squashed_int.hpp" #include "rosa/support/type_helper.hpp" #include "rosa/support/types.hpp" #include #include namespace rosa { // Compile-time list of all built-in types. // NOTE: Appending new types to the end of this list maintains backward // compatibility in the sense that old builtin types have the same type number // associated to them in both the old and new versions. But changing any of // the already present types in the list breaks that backward compatibility. // Should compatibility be broken, step TypeNumberVersion below! // NOTE: Keep this list in sync with the definition of NumberedTypeNames. using BuiltinTypes = TypeList; // Indicates the version number of BuiltinTypes. Software with the same version // number are supposed to have backward compatible type numbering. // NOTE: See note above on backward compatiblity of BultinTypes. constexpr size_t TypeNumberVersion = 0; // The number of built-in types. static constexpr size_t NumberOfBuiltinTypes = TypeListSize::Value; // Anonymous namespace for helper facilities, consider it private. namespace { // Tells if T is not UnitType. template struct IsNotUnitType { static constexpr bool Value = !std::is_same::value; }; } // End namespace // Integer type to store type numbers. // NOTE: The narrowest unsigned integer type that is wide enough to represent // NumberOfBuiltinTypes different values. using type_nr_t = typename TypeListFind::Type, IsNotUnitType>::Type::Second; // Turn type_nr_t into a strongly typed enumeration, so TypeNumbers can be used // in a type-safe way. enum class TypeNumber : type_nr_t {}; // A type to cast type numbers into in order to output them to streams as // numbers and not ASCII-codes. // NOTE: Use it for safety, necessary for printing uint8_t values. using printable_tn_t = PRINTABLE(type_nr_t); // Helper preprocessor macro to cast type numbers into printable_tn_t. #define PRINTABLE_TN(N) static_cast(N) // Converts a TypeNumber into string. inline std::string to_string(const TypeNumber TN) { return std::to_string(static_cast(TN)); } // Computes the type number for T. // NOTE: TypeNumber is the index of T in BuiltinTypes starting from 1, // index 0 indicates a non-builtin type. -template ::value> +template struct TypeNumberOf { - static constexpr TypeNumber Value = - static_cast(TypeListIndexOf::Value + 1); -}; - -template struct TypeNumberOf { - using Type = squashed_int_t; - - static constexpr TypeNumber Value = - static_cast(TypeListIndexOf::Value + 1); + static constexpr TypeNumber Value = static_cast( + TypeListIndexOf>::Value + 1); }; -template <> struct TypeNumberOf { +template <> struct TypeNumberOf { static constexpr TypeNumber Value = static_cast(TypeListIndexOf::Value + 1); }; -template struct TypeNumberOf, false> { +template struct TypeNumberOf> { static constexpr TypeNumber Value = TypeNumberOf::Value; }; // List of all type names, indexed via TypeNumber. // NOTE: Keep this definition in sync with BuiltinTypes. constexpr std::array NumberedTypeNames {{ "atom", "i16", "i32", "i64", "i8", "ldouble", "str", "u16", "u32", "u64", "u8", "unit", "bool", "double", "float" }}; // Tells if the given TypeNumber is valid in the software. // NOTE: A type number generated by an incompatible version may be valid but // supposed to denote a type different than that in the current software. constexpr bool validTypeNumber(const TypeNumber TN) { // FIXME: Duplication of static_cast into a const variable would be // possible in C++14. return 0 < static_cast(TN) && static_cast(TN) <= NumberOfBuiltinTypes; } // Computes the corresponding builtin type with some information from a type // number. // PRE: validTypeNumber(TN) template struct TypeForNumber { STATIC_ASSERT(validTypeNumber(TN), "not a valid type number"); static constexpr type_nr_t TNI = static_cast(TN); using Type = typename TypeListAt::Type; static constexpr size_t Size = sizeof(Type); static constexpr const char *Name = NumberedTypeNames[TNI - 1]; }; } // End namespace rosa #endif // ROSA_SUPPORT_TYPE_NUMBERS_HPP