Page MenuHomePhorge

type_token.hpp
No OneTemporary

Size
6 KB
Referenced Files
None
Subscribers
None

type_token.hpp

/******************************************************************************
*
* File: type_token.hpp
*
* Contents: Facilities for encoding TypeLists as unsigned integer values.
*
* Copyright 2017
*
* Author: David Juhasz (david.juhasz@tuwien.ac.at)
*
******************************************************************************/
#ifndef ROSA_SUPPORT_TYPE_TOKEN_HPP
#define ROSA_SUPPORT_TYPE_TOKEN_HPP
#include "rosa/support/type_numbers.hpp"
namespace rosa {
// NOTE on compatibility between different versions of the type token
// implementation:
// Different software versions produce compatible type tokens as long as
// backward compatibility of BuiltinTypes is maintained (denoted by
// TypeNumberVersion, see a note on that) and the type token implementation
// uses the same type as token_t (boiling down to the same token::TokenBits
// value) and the same 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.
// 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 token_t.
using token_t = uint64_t;
// Sanity check in case someone would change token_t.
STATIC_ASSERT(std::is_unsigned<token_t>::value,
"token_t is not an unsigned integer");
// Turn token_t into a strongly typed enumeration, so 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(token_t);
// Helper preprocessor macro to cast tokens into printable_token_t.
#define PRINTABLE_TOKEN(T) static_cast<printable_token_t>(T)
// Converts a Token into string.
inline std::string to_string(const Token T) {
return std::to_string(static_cast<token_t>(T));
}
// Nested namespace for protecting constants related to type tokens.
namespace token {
// The number of bits in one token.
constexpr size_t TokenBits = sizeof(Token) * 8;
// The number of bits a builtin type can be uniquely encoded into, that is any
// valid 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 BuiltinTypes is
// extended.
constexpr size_t RepresentationBits = log2(NumberOfBuiltinTypes) + 1;
// Maximal size of uniquely tokenizable TypeList.
constexpr size_t MaxTokenizableListSize = TokenBits / RepresentationBits;
} // End namespace token
// Generates a token, unsigned integer representation, for the TypeList.
// NOTE: The TypeList cannot have more than MaxTokenizableListSize elements and
// must be a subset of BuiltinTypes with respect to squashed integers.
// NOTE: A generated token uniquely represents a list of types, except for
// AtomConstant types. Observe that any AtomConstant is encoded as the type
// AtomValue. The type information on all separate AtomConstant types are lost
// and replaced by the AtomValue type whose actual value needs to be considered
// in order to obtain the original AtomConstant type and so the full type
// information on the encoded TypeList.
template <typename List> struct TypeListTokenImpl;
template <> struct TypeListTokenImpl<EmptyTypeList> {
static constexpr Token Value = static_cast<Token>(0);
};
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));
};
template <typename List> struct TypeListToken;
template <typename... Ts> struct TypeListToken<TypeList<Ts...>> {
// NOTE: TypeNumber is computed against 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 TypeListTokenImpl.
STATIC_ASSERT((TypeListSize<List>::Value <= token::MaxTokenizableListSize),
"too long list of types");
static constexpr Token Value = TypeListTokenImpl<List>::Value;
};
// Convenience template turning a list of types into a TypeList to generate
// TypeListToken for it.
template <typename... Ts> using TypeToken = TypeListToken<TypeList<Ts...>>;
// Anonymous namespace with helper facilities, consider it private.
namespace {
// Extracts the type number of the first encoded type of T.
// NOTE: The returned type number is not validated.
inline TypeNumber typeNumberOfHeadOfToken(const Token T) {
return static_cast<TypeNumber>(static_cast<token_t>(T) &
((1 << token::RepresentationBits) - 1));
}
} // End namespace
// Tells if the given Token is valid, can be decoded by the current software.
// NOTE: Validation gives a correct result only when Token was generated by a
// compatible software (see note above).
bool validToken(const Token T);
// Tells if the token does encode an empty list.
bool emptyToken(const Token T);
// Tells how many types are encoded in T.
size_t lengthOfToken(const Token T);
// Tells the full memory size of the list encoded in T.
// PRE: validToken(T)
size_t sizeOfValuesOfToken(const Token T);
// Tells the memory size of the first type encoded in T.
// PRE: !empty(T) && validToken(T)
size_t sizeOfHeadOfToken(const Token T);
// Tells the name of the first type encoded in T.
// PRE: !empty(T) && validToken(T)
const char *nameOfHeadOfToken(const Token T);
// Drops the head element of the encoded list.
void dropHeadOfToken(Token &T);
// Drops the first N element of the encoded list.
void dropNOfToken(Token &T, const size_t N);
// Tells if the head of the encoded list is of type Type.
// PRE: !empty(T) && validToken(T)
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, Mar 1, 5:16 PM (50 m, 30 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
287522
Default Alt Text
type_token.hpp (6 KB)

Event Timeline