Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F360754
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Size
13 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/include/rosa/support/type_token.hpp b/include/rosa/support/type_token.hpp
index 7d9643e..32794c8 100644
--- a/include/rosa/support/type_token.hpp
+++ b/include/rosa/support/type_token.hpp
@@ -1,325 +1,348 @@
//===-- rosa/support/type_token.hpp -----------------------------*- C++ -*-===//
//
// The RoSA Framework
//
// Distributed under the terms and conditions of the Boost Software License 1.0.
// See accompanying file LICENSE.
//
// If you did not receive a copy of the license file, see
// http://www.boost.org/LICENSE_1_0.txt.
//
//===----------------------------------------------------------------------===//
///
/// \file rosa/support/type_token.hpp
///
/// \author David Juhasz (david.juhasz@tuwien.ac.at)
///
-/// \date 2017-2020
+/// \date 2017-2021
///
/// \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 \c rosa::BuiltinTypes is maintained (denoted by
/// \c rosa::TypeNumberVersion) and the type token implementation uses the same
/// type as \c rosa::token_t (boiling down to the same \c rosa::token::TokenBits
-/// value) and the same \c 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.
+/// value) and the same \c rosa::token::RepresentationBits value (denoted by
+/// \c rosa::token::RepresentationVersion). Thus, interacting software need to
+/// cross-validate the aforementioned values to check compatibility.
+/// Interoperation between compatible sofware is limited to backward
+/// compatiblity, that is built-in 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 \c rosa::token_t.
using token_t = uint64_t;
/// Sanity check in case someone would change \c rosa::token_t.
STATIC_ASSERT(std::is_unsigned<token_t>::value,
"token_t is not an unsigned integer");
/// Turn \c rosa::token_t into a strongly typed enumeration.
///
/// Values of \c rosa::token_t casted to \c rosa::Token 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 \c uint8_t values.
using printable_token_t = printable_t<token_t>;
/// Casts a \c rosa::Token into \c rosa::printable_token_t.
///
/// \param T \c rosa::Token to cast
#define PRINTABLE_TOKEN(T) static_cast<printable_token_t>(T)
/// Encloses constants related to the implementation of \c rosa::Token.
namespace token {
/// The number of bits in one \c rosa::Token.
constexpr size_t TokenBits = sizeof(Token) * 8;
-/// The number of bits a builtin type can be uniquely encoded into, that is any
+/// The number of bits a built-in type can be uniquely encoded into, that is any
/// valid \c 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 \c rosa::BuiltinTypes
-/// is extended.
-constexpr size_t RepresentationBits = log2(NumberOfBuiltinTypes) + 1;
+/// The value should be not less than the binary logarithm of
+/// \c rosa::NumberOfBuiltinTypes.
+///
+/// \note The value is defined by an integer literal so it does not directly
+/// vary with the number of built-in types. The actual value allows one extra
+/// bit position for encoding (as of the time of writing this comment), which
+/// allows for more addition to the list of \c rosa::BuiltinTypes. Changing this
+/// value breaks compatibility of type encoding. Should compatibility be broken,
+/// step \c rosa::token::RepresentationVersion below!
+constexpr size_t RepresentationBits = 5;
+
+/// Sanity check in case someone adds built-in types without adjusting
+/// \c rosa::token::RepresentationBits.
+STATIC_ASSERT(log2(NumberOfBuiltinTypes) <= RepresentationBits,
+ "Cannot encode all built-in types");
+
+/// Indicates the version number of details in \c rosa::token.
+///
+/// Software with the same version number are supposed to have
+/// compatible type encoding.
+///
+/// \sa \c rosa::token::RepresentationBits on compatibility.
+constexpr size_t RepresentationVersion = 0;
/// Maximal size of uniquely tokenizable \c rosa::TypeList.
constexpr size_t MaxTokenizableListSize = TokenBits / RepresentationBits;
} // End namespace token
/// Integer type to store length of a \c rosa::Token.
///
/// \note The narrowest unsigned integer type that is wide enough to
/// represent \c rosa::token::MaxTokenizableListSize different values.
using token_size_t = typename TypeListFind<
typename TypeListDrop<log2(token::MaxTokenizableListSize) / 8 + 1,
IntegerTypesBySize>::Type,
IsNotNoneType>::Type::Second;
/// \defgroup TypeListTokenImpl Implementation of rosa::TypeListToken
///
/// \brief Generates a \c rosa::Token for a squashed \c rosa::TypeList.
///
/// \note Only to be used by the implementation of \c rosa::TypeListToken.
///@{
/// Declaration of the template.
///
/// \tparam List \c rosa::TypeList to generate \c rosa::Token for
template <typename List> struct TypeListTokenImpl;
/// Specialization for \c rosa::EmptyTypeList.
template <> struct TypeListTokenImpl<EmptyTypeList> {
static constexpr Token Value = static_cast<Token>(0);
};
/// Specialization for a non-empty \c 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 \c rosa::Token for a \c rosa::TypeList.
///
/// \c rosa::Token for a \c rosa::TypeList \c List can be obtained as \code
/// TypeListToken<List>::Value
/// \endcode
///
/// \note The \c rosa::TypeList cannot have more than
/// \c rosa::token::MaxTokenizableListSize elements and must be a subset of
/// \c rosa::BuiltinTypes with respect to squashed integers.
///
/// \note A generated \c rosa::Token uniquely represents a list of types, except
/// for \c rosa::AtomConstant types. Observe that any \c rosa::AtomConstant is
/// encoded as the type \c rosa::AtomValue. The type information on all separate
/// \c rosa::AtomConstant types are lost and replaced by the \c rosa::AtomValue
/// type whose actual value needs to be used in order to obtain the original
/// \c rosa::AtomConstant type and so the full type information on the encoded
/// \c rosa::TypeList.
///
///@{
/// Declaration of the template.
///
/// \tparam List \c rosa::TypeList to generate \c rosa::Token for
template <typename List> struct TypeListToken;
/// Implementation using \c rosa::TypeListTokenImpl.
template <typename... Ts> struct TypeListToken<TypeList<Ts...>> {
/// \note \c rosa::TypeNumber is computed against \c rosa::squashed_t, 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 \c rosa::TypeListTokenImpl.
STATIC_ASSERT((TypeListSize<List>::Value <= token::MaxTokenizableListSize),
"too long list of types");
/// The \c rosa::Token for \p List.
static constexpr Token Value = TypeListTokenImpl<List>::Value;
};
///@}
/// Convenience template to generate \c rosa::Token for a list of types.
template <typename... Ts> using TypeToken = TypeListToken<TypeList<Ts...>>;
/// Tells if a given \c rosa::Token is valid.
///
/// A \c rosa::Token is considered valid if it can be decoded by the current
/// software.
///
-/// \note Validation gives a correct result only when \p T was generated by a
-/// compatible software.
+/// \note A \c rosa::Token generated by an incompatible version may be
+/// valid but may encode types that are different from what is decoded by the
+/// current software. That is why this validation needs to be done in connection
+/// to checking \c rosa::token::RepresentationVersion and
+/// \c rosa::TypeNumberVersion for compatibility.
///
/// \sa Note for type_token.hpp on compatibility.
///
/// \param T \c rosa::Token to validate
///
/// \return if \p T is valid
bool validToken(const Token T);
/// Tells if a \c rosa::Token does encode an empty list of types.
///
/// \param T \c rosa::Token to check
///
/// \return if \p T encodes an empty list of types
bool emptyToken(const Token T);
/// Tells how many types are encoded in a \c rosa::Token.
///
/// \param T \c rosa::Token to check
///
/// \return how many types are encoded in \p T
token_size_t lengthOfToken(const Token T);
/// Extracts the \c rosa::TypeNumber of the first encoded type of a
/// \c rosa::Token.
///
/// \note The returned type number is not validated.
///
/// \param T \c rosa::Token to take the first \c rosa::TypeNumber from
///
/// \return the first \c rosa::TypeNumber encoded in \p T
inline TypeNumber headOfToken(const Token T) {
return static_cast<TypeNumber>(static_cast<token_t>(T) &
((1 << token::RepresentationBits) - 1));
}
/// Tells the memory size of the first type encoded in a \c rosa::Token.
///
/// \param T \c rosa::Token to check the first encoded type of
///
/// \return memory size of the first type encoded in \p T
///
/// \pre \p T is not empty and valid:\code
/// !empty(T) && validToken(T)
/// \endcode
size_t sizeOfHeadOfToken(const Token T);
/// Tells the required memory alignment of the first type encoded in a \c
/// rosa::Token.
///
/// \param T \c rosa::Token to check the first encoded type of
///
/// \return memory alignment of the first type encoded in \p T
///
/// \pre \p T is not empty and valid:\code
/// !empty(T) && validToken(T)
/// \endcode
size_t alignmentOfHeadOfToken(const Token T);
/// Gives the textual representation of the first type encoded in a
/// \c rosa::Token.
///
/// \param T \c rosa::Token to take the name of its first encoded type
///
/// \return textual representation of the first type encoded in \p T
///
/// \pre \p T is not empty and valid:\code
/// !empty(T) && validToken(T)
/// \endcode
const char *nameOfHeadOfToken(const Token T);
/// Updates a \c rosa::Token by dropping its first encoded type.
///
/// \param [in,out] T \c rosa::Token to drop the first encoded type of
void dropHeadOfToken(Token &T);
/// Updates a \c rosa::Token by dropping a number of its first encoded types
///
/// \param [in,out] T \c rosa::Token to drop the first \p N encoded types of
/// \param N the number of types to drop from \p T
void dropNOfToken(Token &T, const size_t N);
/// Tells what type is encoded at Position \p Pos in the \c rosa::Token \p T
///
/// \param T \c rosa::Token to check
/// \param Pos the position to check
///
/// \return \c rosa::TypeNumber of the type encodeded at position \p Pos of \c
/// rosa::Token \p T
///
/// \pre \p T is valid and it encodes \p Pos types: \code
/// validToken(T) && Pos < static_cast<size_t>(lengthOfToken(T))
/// \endcode
inline TypeNumber typeAtPositionOfToken(const Token T, const size_t Pos) {
ASSERT(validToken(T) && Pos < static_cast<size_t>(lengthOfToken(T)));
Token TT = T;
dropNOfToken(TT, Pos);
return headOfToken(TT);
}
/// Tells if the first encoded type of a \c rosa::Token is a given type.
///
/// \tparam Type type to match the first encoded type of \p T against
///
/// \param T \c rosa::Token whose first encoded type is to be matched against
/// \p Type
///
/// \return if the first encoded type of \p T is \p Type
///
/// \pre \p 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 == headOfToken(T);
}
} // End namespace rosa
namespace std {
/// Converts a \c rosa::Token into \c std::string.
///
/// \param T \c rosa::Token to convert
///
/// \return \c std::string representing \p T
inline string to_string(const rosa::Token T) {
return to_string(static_cast<rosa::token_t>(T));
}
/// Dumps a \c rosa::Token to a given \c std::ostream.
///
/// \param [in,out] OS output stream to dump to
/// \param T \c rosa::Token to dump
///
/// \return \p OS after dumping \p N to it
inline ostream &operator<<(ostream &OS, const rosa::Token &T) {
OS << to_string(T);
return OS;
}
} // End namespace std
#endif // ROSA_SUPPORT_TYPE_TOKEN_HPP
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, May 17, 4:00 AM (5 h, 21 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
141498
Default Alt Text
(13 KB)
Attached To
Mode
R20 SoC_Rosa_repo
Attached
Detach File
Event Timeline
Log In to Comment