Page MenuHomePhorge

type_token.hpp
No OneTemporary

Size
9 KB
Referenced Files
None
Subscribers
None

type_token.hpp

/**************************************************************************//**
*
* \file rosa/support/type_token.hpp
*
* \author David Juhasz (david.juhasz@tuwien.ac.at)
*
* \date 2017
*
* \brief Facilities for encoding TypeLists as unsigned integer values.
*
* \note **On the compatibility between different versions of the type token
* implementation:**
* Different software versions produce compatible type tokens as long as
* *backward compatibility* of `rosa::BuiltinTypes` is maintained (denoted by
* `rosa::TypeNumberVersion`) and the type token implementation uses the same
* type as `rosa::token_t` (boiling down to the same `rosa::token::TokenBits`
* value) and the same `rosa::token::RepresentationBits` value. Thus,
* interacting software need to cross-validate the aforementioned values to
* check compatibility. Interoperation between compatible sofware is limited
* to backward compatiblity, that is builtin types defined in both software
* versions are handled correctly but a newer system may produce a type token
* which is invalid in an old one. Therefore, tokens obtained from a compatible
* remote system need to be validated.
*
******************************************************************************/
#ifndef ROSA_SUPPORT_TYPE_TOKEN_HPP
#define ROSA_SUPPORT_TYPE_TOKEN_HPP
#include "rosa/support/type_numbers.hpp"
namespace rosa {
/// Integer type to store type tokens.
/// \note The trade-off between the binary overhead of type encoding and the
/// maximal size of encodable lists can be tuned by using unsigned integer types
/// of different widths as `rosa::token_t`.
using token_t = uint64_t;
/// Sanity check in case someone would change `rosa::token_t`.
STATIC_ASSERT(std::is_unsigned<token_t>::value,
"token_t is not an unsigned integer");
/// Turn `rosa::token_t` into a strongly typed enumeration.
///
/// Values of `rosa::token_t` casted to `rosa::Tokens` can be used in a
/// type-safe way.
enum class Token : token_t {};
/// A type to cast tokens 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_token_t = printable_t<token_t>;
/// Casts a `rosa::Token` into `rosa::printable_token_t`.
#define PRINTABLE_TOKEN(T) static_cast<printable_token_t>(T)
/// Converts a `rosa::Token` into `std::string`.
///
/// \param T `Token` to convert
///
/// \return `string` representing `T`
inline std::string to_string(const Token T) {
return std::to_string(static_cast<token_t>(T));
}
/// Encloses constants related to the implementation of `rosa::Token`.
namespace token {
/// The number of bits in one `rosa::Token`.
constexpr size_t TokenBits = sizeof(Token) * 8;
/// The number of bits a builtin type can be uniquely encoded into, that is any
/// valid `rosa::TypeNumber` can fit into.
/// \note There is one extra bit position added for encoding so that providing a
/// better chance to maintain backward comaptibility when `rosa::BuiltinTypes`
/// is extended.
constexpr size_t RepresentationBits = log2(NumberOfBuiltinTypes) + 1;
/// Maximal size of uniquely tokenizable `rosa::TypeList`.
constexpr size_t MaxTokenizableListSize = TokenBits / RepresentationBits;
} // End namespace token
/// \defgroup TypeListTokenImpl
/// \brief Generates a `rosa::Token` for a squashed `rosa::TypeList`.
///
/// \note Only to be used by the implementation of `rosa::TypeListToken`.
///@{
/// Declaration of the template.
///
/// \tparam List `TypeList` to generate `Token` for
template <typename List> struct TypeListTokenImpl;
/// Specialization for `rosa::EmptyTypeList`.
template <> struct TypeListTokenImpl<EmptyTypeList> {
static constexpr Token Value = static_cast<Token>(0);
};
/// Specialization for a non-empty `rosa::TypeList`.
template <typename T, typename... Ts>
struct TypeListTokenImpl<TypeList<T, Ts...>> {
static constexpr TypeNumber TN = TypeNumberOf<T>::Value;
// Check if the generated type number is valid.
STATIC_ASSERT(validTypeNumber(TN), "non-builtin type");
static constexpr Token Value = static_cast<Token>(
(static_cast<token_t>(TypeListTokenImpl<TypeList<Ts...>>::Value)
<< token::RepresentationBits) |
static_cast<type_nr_t>(TN));
};
///@}
/// \name TypeListToken
/// \brief Generates a `rosa::Token` for a `rosa::TypeList`.
///
/// `rosa::Token` for a `rosa::TypeList` `List` can be obtained as \code
/// TypeListToken<List>::Value
/// \endcode
///
/// \note The `rosa::TypeList` cannot have more than
/// `rosa::token::MaxTokenizableListSize` elements and must be a subset of
/// `rosa::BuiltinTypes` with respect to squashed integers.
/// \note A generated `rosa::Token` uniquely represents a list of types, except
/// for `rosa::AtomConstant` types. Observe that any `rosa::AtomConstant` is
/// encoded as the type `rosa::AtomValue`. The type information on all separate
/// `rosa::AtomConstant` types are lost and replaced by the `rosa::AtomValue`
/// type whose actual value needs to be in order to obtain the
/// original `rosa::AtomConstant` type and so the full type information on the
/// encoded `rosa::TypeList`.
///
///@{
/// Declaration of the template.
///
/// \tparam List `TypeList` to generate `Token` for
template <typename List> struct TypeListToken;
/// Implementation using `rosa::TypeListTokenImpl`.
template <typename... Ts> struct TypeListToken<TypeList<Ts...>> {
/// \note `rosa::TypeNumber` is computed against `rosa::squased_int_t` for
/// integral types, so let's do the same here.
using List = typename SquashedTypeList<TypeList<Ts...>>::Type;
/// Check the length of the list here.
/// \note Type validation is done one-by-one in `rosa::TypeListTokenImpl`.
STATIC_ASSERT((TypeListSize<List>::Value <= token::MaxTokenizableListSize),
"too long list of types");
/// The `rosa::Token` for `List`.
static constexpr Token Value = TypeListTokenImpl<List>::Value;
};
///@}
/// Convenience template to generate `rosa::Token` for a list of types.
template <typename... Ts> using TypeToken = TypeListToken<TypeList<Ts...>>;
/// Anonymous namespace with helper facilities, consider it private.
namespace {
/// Extracts the `rosa::TypeNumber` of the first encoded type of a
/// `rosa::Token`.
///
/// \note The returned type number is not validated.
///
/// \param T `Token` to take the first `TypeNumber` from
///
/// \return the first `TypeNumber` encoded in `T`
inline TypeNumber typeNumberOfHeadOfToken(const Token T) {
return static_cast<TypeNumber>(static_cast<token_t>(T) &
((1 << token::RepresentationBits) - 1));
}
} // End namespace
/// Tells if a given `rosa::Token` is valid.
///
/// A `rosa::Token` is considered valid if it can be decoded by the current
/// software.
///
/// \note Validation gives a correct result only when `T` was generated by a
/// compatible software.
///
/// \sa Note for type_token.hpp on compatibility.
///
/// \param T `Token` to validate
///
/// \return if `T` is valid
bool validToken(const Token T);
/// Tells if a `rosa::Token` does encode an empty list of types.
///
/// \param T `Token` to check
///
/// \return if `T` encodes an empty list of types
bool emptyToken(const Token T);
/// Tells how many types are encoded in a `rosa::Token`.
///
/// \param T `Token` to check
///
/// \return how many types are encoded in `T`
size_t lengthOfToken(const Token T);
/// Tells the full memory size of the types encoded in a `rosa::Token`.
///
/// The full memory size of the types encoded in a `rosa::Token` is the sum of
/// the separate memory sizes of all the types encoded in the `rosa::Token`.
///
/// \param T `Token` to check
///
/// \return full memory size of the types encoded in `T`
///
/// \pre `T` is valid:\code
/// validToken(T)
/// \endcode
size_t sizeOfValuesOfToken(const Token T);
/// Tells the memory size of the first type encoded in a `rosa::Token`.
///
/// \param T `Token` to check the first encoded type of
///
/// \return memory size of the first type encoded in `T`
///
/// \pre `T` is not empty and valid:\code
/// !empty(T) && validToken(T)
/// \endcode
size_t sizeOfHeadOfToken(const Token T);
/// Gives the textual representation of the first type encoded in a
/// `rosa::Token`.
///
/// \param T `Token` to take the name of its first encoded type
///
/// \return textual representation of the first type encoded in `T`
///
/// \pre `T` is not empty and valid:\code
/// !empty(T) && validToken(T)
/// \endcode
const char *nameOfHeadOfToken(const Token T);
/// Updates a `rosa::Token` by dropping its first encoded type.
///
/// \param [in,out] T `Token` to drop the first encoded type of
void dropHeadOfToken(Token &T);
/// Updates a `rosa::Token` by dropping a number of its first encoded types
///
/// \param [in,out] T `Token` to drop the first `N` encoded types of
/// \param N the number of types to drop from `T`
void dropNOfToken(Token &T, const size_t N);
/// Tells if the first encoded type of a `rosa::Token` is a given type.
///
/// \tparam Type type to match the first encoded type of `T` against
///
/// \param T `Token` whose first encoded type is to be matched against `Type`
///
/// \return if the first encoded type of `T` is `Type`
///
/// \pre `T` is not empty and valid:\code
/// !empty(T) && validToken(T)
/// \endcode
template <typename Type>
bool isHeadOfTokenTheSameType(const Token T) {
ASSERT(!emptyToken(T) && validToken(T));
return TypeNumberOf<Type>::Value == typeNumberOfHeadOfToken(T);
}
} // End namespace rosa
#endif // ROSA_SUPPORT_TYPE_TOKEN_HPP

File Metadata

Mime Type
text/x-c++
Expires
Sun, Aug 2, 2:04 AM (1 d, 7 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
323183
Default Alt Text
type_token.hpp (9 KB)

Event Timeline