Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F376176
type_token.hpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Size
11 KB
Referenced Files
None
Subscribers
None
type_token.hpp
View Options
//===-- rosa/support/type_token.hpp -----------------------------*- C++ -*-===//
//
// The RoSA Framework
//
//===----------------------------------------------------------------------===//
///
/// \file rosa/support/type_token.hpp
///
/// \author David Juhasz (david.juhasz@tuwien.ac.at)
///
/// \date 2017-2019
///
/// \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.
///
//===----------------------------------------------------------------------===//
#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
/// 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
;
/// 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::squased_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.
///
/// \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
);
/// Tells the full memory size of the types encoded in a \c rosa::Token.
///
/// The full memory size of the types encoded in a \c rosa::Token is the sum of
/// the separate memory sizes of all the types encoded in the \c rosa::Token.
///
/// \param T \c rosa::Token to check
///
/// \return full memory size of the types encoded in \p T
///
/// \pre \p T is valid:\code
/// validToken(T)
/// \endcode
size_t
sizeOfValuesOfToken
(
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
);
/// 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-c++
Expires
Sun, Jun 8, 8:19 PM (1 d, 7 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
150477
Default Alt Text
type_token.hpp (11 KB)
Attached To
Mode
R20 SoC_Rosa_repo
Attached
Detach File
Event Timeline
Log In to Comment