Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F23080005
type_token.hpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Size
9 KB
Referenced Files
None
Subscribers
None
type_token.hpp
View Options
/**************************************************************************//**
*
* \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
Details
Attached
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)
Attached To
Mode
R20 SoC_Rosa_repo
Attached
Detach File
Event Timeline
Log In to Comment