Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F386453
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Size
55 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/examples/type-facilities/type-facilities.cpp b/examples/type-facilities/type-facilities.cpp
index 696679e..06ce66f 100644
--- a/examples/type-facilities/type-facilities.cpp
+++ b/examples/type-facilities/type-facilities.cpp
@@ -1,94 +1,94 @@
//===-- examples/type-facilities/type-facilities.cpp ------------*- 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 examples/type-facilities/type-facilities.cpp
///
/// \author David Juhasz (david.juhasz@tuwien.ac.at)
///
-/// \date 2017-2019
+/// \date 2017-2020
///
/// \brief An example showcasing various type-related support facilities.
///
//===----------------------------------------------------------------------===//
#include "rosa/config/version.h"
#include "rosa/support/log.h"
#include "rosa/support/terminal_colors.h"
#include "rosa/support/type_token.hpp"
using namespace rosa;
using namespace rosa::terminal;
int main(void) {
LOG_INFO_STREAM << library_string() << " -- " << Color::Red
<< "type facilities" << Color::Default << '\n';
auto &Log = LOG_TRACE_STREAM;
Log << "\nNumberOfBuiltinTypes: " << NumberOfBuiltinTypes
<< "\nTokenBits: " << token::TokenBits
<< "\nRepresentationBits: " << token::RepresentationBits
<< "\nMaxTokenizableListSize: " << token::MaxTokenizableListSize
<< "\n\n";
Log << "Type number information on 'uint8_t':";
constexpr TypeNumber TN = TypeNumberOf<uint8_t>::Value;
Log << "\n type number: " << PRINTABLE_TN(TN)
<< "\n size: " << TypeForNumber<TN>::Size
<< "\n name: " << TypeForNumber<TN>::Name << "\n\n";
Log << "Type number information on 'std::string':";
constexpr TypeNumber TNS = TypeNumberOf<std::string>::Value;
Log << "\n type number: " << PRINTABLE_TN(TNS)
<< "\n size: " << TypeForNumber<TNS>::Size
<< "\n name: " << TypeForNumber<TNS>::Name << "\n\n";
Log << "Type number information of AtomConstants:";
using Atom1 = AtomConstant<atom("atom1")>;
using Atom2 = AtomConstant<atom("atom2")>;
Log << "\n std::is_same<Atom1, Atom2>::value: "
<< std::is_same<Atom1, Atom2>::value << "\n TypeNumberOf<Atom1>::Value: "
<< PRINTABLE_TN(TypeNumberOf<Atom1>::Value)
<< "\n TypeNumberOf<Atom2>::Value: "
<< PRINTABLE_TN(TypeNumberOf<Atom2>::Value)
<< "\n name: " << TypeForNumber<TypeNumberOf<Atom1>::Value>::Name
<< "\n\n";
Log << "Type token information on 'TypeList<uint8_t, uint16_t, "
"std::string>':";
// \c rosa::Token is generated statically.
constexpr Token T = TypeToken<uint8_t, uint16_t, std::string>::Value;
STATIC_ASSERT(
(T == TypeListToken<TypeList<uint8_t, uint16_t, std::string>>::Value),
"alias template definition is wrong");
Token T_ = T; // We need a non-const value for dropping head later.
// Iterate over encoded entries in \c T_.
while (!emptyToken(T_)) {
Log << "\n token: " << PRINTABLE_TOKEN(T_)
<< "\n valid: " << validToken(T_) << "\n empty: " << emptyToken(T_)
<< "\n length: " << static_cast<size_t>(lengthOfToken(T_))
- << "\n full size: " << sizeOfValuesOfToken(T_)
<< "\n head type number: " << PRINTABLE_TN(headOfToken(T_))
<< "\n size of head: " << sizeOfHeadOfToken(T_)
+ << "\n alignment of head: " << alignmentOfHeadOfToken(T_)
<< "\n name of head: " << nameOfHeadOfToken(T_)
<< "\n is head uint8_t: " << isHeadOfTokenTheSameType<uint8_t>(T_)
<< "\n is head uint16_t: " << isHeadOfTokenTheSameType<uint16_t>(T_)
<< "\n is head std::string: "
<< isHeadOfTokenTheSameType<std::string>(T_) << "\nDropping head...";
dropHeadOfToken(T_);
}
// Here when Token became empty.
Log << "\n token: " << PRINTABLE_TOKEN(T_) << "\n empty: " << emptyToken(T_)
<< '\n';
return 0;
}
diff --git a/include/rosa/support/tokenized_storages.hpp b/include/rosa/support/tokenized_storages.hpp
index b11035a..3157a39 100755
--- a/include/rosa/support/tokenized_storages.hpp
+++ b/include/rosa/support/tokenized_storages.hpp
@@ -1,629 +1,655 @@
//===-- rosa/support/tokenized_storages.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/tokenized_storages.hpp
///
/// \author David Juhasz (david.juhasz@tuwien.ac.at)
///
-/// \date 2017-2019
+/// \date 2017-2020
///
/// \brief Definition of storage helper template for storing values in a
/// type-safe way based on type tokens.
///
//===----------------------------------------------------------------------===//
#ifndef ROSA_SUPPORT_TOKENIZED_STORAGES_HPP
#define ROSA_SUPPORT_TOKENIZED_STORAGES_HPP
#include "rosa/support/log.h"
#include "rosa/support/type_token.hpp"
#include <memory>
#include <vector>
namespace rosa {
/// Defines a simple interface for storing and accessing values of different
/// types.
///
/// While the interface provides features to access values and know their
/// types, it is the users responsibility to use particular values according to
/// their actual types. No facilities for type-safe access of values is
/// provided by the class.
///
/// \see \c rosa::TokenizedStorage for a type-safe specialization of the
/// interface.
class AbstractTokenizedStorage {
protected:
/// Protected constructor restricts instantiation for derived classes.
AbstractTokenizedStorage(void) noexcept = default;
public:
/// No copying and moving of \c rosa::AbstractTokenizedStorage instances.
///@{
AbstractTokenizedStorage(const AbstractTokenizedStorage &) = delete;
AbstractTokenizedStorage &
operator=(const AbstractTokenizedStorage &) = delete;
AbstractTokenizedStorage(AbstractTokenizedStorage &&Other) = delete;
AbstractTokenizedStorage &operator=(AbstractTokenizedStorage &&) = delete;
///@}
/// Destroys \p this object.
virtual ~AbstractTokenizedStorage(void) noexcept = default;
/// Tells how many values are stored in \p this object.
///
/// \return number of values stored in \p this object
virtual size_t size(void) const noexcept = 0;
/// Tells the type of the value stored at a position.
///
/// \param Pos the index of the value whose type is to returned
///
/// \return \c rosa::TypeNumber for the value stored at index \p Pos
///
/// \pre \p Pos is a valid index:\code
/// Pos < size()
/// \endcode
virtual TypeNumber typeAt(const token_size_t Pos) const noexcept = 0;
/// Provides an untyped pointer for the value stored at a position.
///
/// \param Pos the index of the value to return an untyped pointer for
///
/// \return untyped pointer for the value stored at index \p Pos
///
/// \pre \p Pos is a valid index:\code
/// Pos < size()
/// \endcode
virtual void *pointerTo(const token_size_t Pos) noexcept = 0;
/// Provides a constant untyped pointer for the value stored at a position.
///
/// \param Pos the index of the value to return an untyped pointer for
///
/// \return constant untyped pointer for the value stored at index \p Pos
///
/// \pre \p Pos is a valid index:\code
- /// Pos < Offsets.size()
+ /// Pos < size()
/// \endcode
virtual const void *pointerTo(const token_size_t Pos) const noexcept = 0;
};
/// Template class storing values and providing dynamic type-safe access to
/// them in a lightweight way based on type tokens.
///
/// \see rosa/support/type_token.hpp
///
/// \tparam Types types whose values are to be stored
template <typename... Types> class TokenizedStorage;
/// \defgroup TokenizedStorageForTypeList Implementation of
/// rosa::TokenizedStorageForTypeList
///
/// \brief Transforms a \c rosa::TypeList instance to the corresponding
/// \c rosa::TokenizedStorage instance.
///
/// A \c rosa::TypeList \c List instance can be turned into a corresponding \c
/// rosa::TokenizedStorage instance as \code
/// typename TokenizedStorageForTypeList<List>::Type
/// \endcode
///
/// For example, the following expression evaluates to `true`: \code
/// std::is_same<typename TokenizedStorageForTypeList<TypeList<T1, T2>>::Type,
/// TokenizedStorage<T1, T2>>::value
/// \endcode
///@{
/// Declaration of the template.
///
/// \tparam List \c rosa::TypeList to transform
template <typename List> struct TokenizedStorageForTypeList;
/// Implementation of the template for \c rosa::TypeList instances.
template <typename... Ts> struct TokenizedStorageForTypeList<TypeList<Ts...>> {
using Type = TokenizedStorage<Ts...>;
};
///@}
/// Nested namespace with implementation for \c rosa::TokenizedStorage, consider
/// it private.
namespace {
/// Initializes a pre-allocated memory area with values from constant lvalue
/// references.
///
/// \tparam Types types whose values are to be stored
///
/// \param Arena pre-allocated memory area to store values to
/// \param Ts the values to store in \p Arena
///
/// \note \p Arena needs to be a valid pointer to a memory area big enough for
/// values of \p Types.
template <typename... Types>
inline void createArenaElements(void *const Arena,
const Types &... Ts) noexcept;
/// \defgroup createLvalueArenaElement Implementation of creating lvalue arena
/// elements
///
/// Stores values from constant lvalue references into a pre-allocated memory
/// area.
///
/// \note To be used by the implementation of \c createArenaElements.
///
/// \todo Document these functions.
///@{
/// \note This terminal case is used for both constant lvalue references and
/// value references.
template <size_t Pos>
inline void createArenaElement(void *const,
const std::vector<size_t> &Offsets) {
ASSERT(Pos == Offsets.size());
}
template <size_t Pos, typename Type, typename... Types>
inline void createArenaElement(void *const Arena,
const std::vector<size_t> &Offsets,
const Type &T, const Types &... Ts) noexcept {
ASSERT(Arena != nullptr && Pos < Offsets.size());
new (static_cast<Type *>(static_cast<void *>(static_cast<uint8_t *>(Arena) +
Offsets[Pos]))) Type(T);
createArenaElement<Pos + 1>(Arena, Offsets, Ts...);
}
template <size_t Pos, AtomValue V, typename... Types>
inline void
createArenaElement(void *const Arena, const std::vector<size_t> &Offsets,
const AtomConstant<V> &, const Types &... Ts) noexcept {
ASSERT(Arena != nullptr && Pos < Offsets.size());
*static_cast<AtomValue *>(
static_cast<void *>(static_cast<uint8_t *>(Arena) + Offsets[Pos])) = V;
createArenaElement<Pos + 1>(Arena, Offsets, Ts...);
}
///@}
/// Implementation of the template.
///
/// \tparam Types types of values to store
///
/// \param Arena pre-allocated memory area to store values to
/// \param Ts values to store in \p Arena
///
/// \pre \p Arena is not \p nullptr.
template <typename... Types>
inline void createArenaElements(void *const Arena,
const Types &... Ts) noexcept {
ASSERT(Arena != nullptr);
- createArenaElement<0>(Arena, TokenizedStorage<Types...>::Offsets, Ts...);
+ createArenaElement<0>(Arena, TokenizedStorage<Types...>::offsets(), Ts...);
}
/// Initializes a pre-allocated memory area with values from rvalue references.
///
/// \tparam Types types whose values are to be stored
///
/// \param Arena pre-allocated memory area to store values to
/// \param Ts the values to store in \p Arena
///
/// \note \p Arena needs to be a valid pointer to a memory area big enough for
/// values of \p Types.
template <typename... Types>
inline void createArenaElements(void *const Arena, Types &&... Ts) noexcept;
/// \defgroup createRvalueArenaElement Implementation of creating rvalue arena
/// elements
///
/// Stores values from rvalue references into a pre-allocated memory area.
///
/// \note To be used by the implementation of \c createArenaElements.
///
/// \todo Document these functions.
///@{
template <size_t Pos, typename Type, typename... Types>
inline void createArenaElement(void *const Arena,
const std::vector<size_t> &Offsets, Type &&T,
Types &&... Ts) noexcept {
ASSERT(Arena != nullptr && Pos < Offsets.size());
new (static_cast<Type *>(static_cast<void *>(
static_cast<uint8_t *>(Arena) + Offsets[Pos]))) Type(std::move(T));
createArenaElement<Pos + 1>(Arena, Offsets, std::move(Ts)...);
}
template <size_t Pos, AtomValue V, typename... Types>
inline void createArenaElement(void *const Arena,
const std::vector<size_t> &Offsets,
AtomConstant<V> &&, Types &&... Ts) noexcept {
ASSERT(Arena != nullptr && Pos < Offsets.size());
*static_cast<AtomValue *>(
static_cast<void *>(static_cast<uint8_t *>(Arena) + Offsets[Pos])) = V;
createArenaElement<Pos + 1>(Arena, Offsets, std::move(Ts)...);
}
///@}
/// Implementation of the template.
///
/// \tparam Types types of values to store
///
/// \param Arena pre-allocated memory area to store values to
/// \param Ts values to store in \p Arena
///
/// \pre \p Arena is not \c nullptr.
template <typename... Types>
inline void createArenaElements(void *const Arena, Types &&... Ts) noexcept {
ASSERT(Arena != nullptr);
- createArenaElement<0>(Arena, TokenizedStorage<Types...>::Offsets,
+ createArenaElement<0>(Arena, TokenizedStorage<Types...>::offsets(),
std::move(Ts)...);
}
/// Destroys values allocated by \c createArenaElements.
///
/// \tparam Types types whose values are stored in \p Arena
///
/// \param Arena the memory area to destroy values from
///
/// \note \p Arena needs to be a valid pointer to a memory area where values of
/// \p Types are stored.
template <typename... Types>
inline void destroyArenaElements(void *const Arena) noexcept;
/// \defgroup destroyArenaElement Implementation of destroying arena elements
///
/// Destroys values from a memory area.
///
/// \note To be used by the implementation of \c destroyArenaElements.
///
/// \todo Document these functions.
///@{
template <size_t Pos>
inline void destroyArenaElement(void *const,
const std::vector<size_t> &Offsets) noexcept {
ASSERT(Pos == Offsets.size());
}
template <size_t Pos, typename Type, typename... Types>
inline void destroyArenaElement(void *const Arena,
const std::vector<size_t> &Offsets) noexcept {
ASSERT(Arena != nullptr && Pos < Offsets.size());
static_cast<Type *>(
static_cast<void *>(static_cast<uint8_t *>(Arena) + Offsets[Pos]))
->~Type();
destroyArenaElement<Pos + 1, Types...>(Arena, Offsets);
}
///@}
/// Implementation of the template.
///
/// \tparam Types types of values to destroy
///
/// \param Arena the memory area to destroy values from
///
/// \pre \p Arena is not \c nullptr.
template <typename... Types>
inline void destroyArenaElements(void *const Arena) noexcept {
ASSERT(Arena != nullptr);
- destroyArenaElement<0, Types...>(Arena, TokenizedStorage<Types...>::Offsets);
+ destroyArenaElement<0, Types...>(Arena,
+ TokenizedStorage<Types...>::offsets());
}
} // End namespace
/// Implementation of the template \c rosa::TokenizedStorage as a
/// specialization of \c rosa::AbstractTokenizedStorage.
///
/// The class provides facilities for storing values and providing type-safe
/// access to them.
///
/// \tparam Types types of values to store
template <typename... Types>
class TokenizedStorage : public AbstractTokenizedStorage {
public:
/// \c rosa::Token for the stored values.
static constexpr Token ST = TypeToken<std::decay_t<Types>...>::Value;
- /// Byte offsets to access stored values in \c rosa::TokenizedStorage::Arena.
- static const std::vector<size_t> Offsets;
-
-private:
- /// A BLOB storing all the values one after the other.
- void *const Arena;
-
/// Generates byte offsets for accessing values stored in
/// \c rosa::TokenizedStorage::Arena.
///
+ /// \note Alignment requirement of each value is taken into account.
+ ///
/// \return \c std::vector containing byte offsets for accessing values stored
/// in \c rosa::TokenizedStorage::Arena
- static std::vector<size_t> offsets(void) noexcept {
- Token T = ST; // Need a mutable copy.
- const token_size_t N = lengthOfToken(T); // Number of types encoded in \c T.
- std::vector<size_t> O(N); // Allocate vector of proper size.
- // Do nothing for 0 elements.
- if (N > 0) {
+ static const std::vector<size_t> &offsets(void) noexcept {
+ static std::vector<size_t> Offsets;
+
+ // Initialize Offsets during the first invocation.
+ if (Offsets.empty()) {
+ Token T = ST; // Need a mutable copy.
+ const token_size_t N =
+ lengthOfToken(T); // Number of types encoded in \c T.
+ Offsets.resize(N); // Allocate proper size right away.
+
+ ASSERT(N > 0); // Sanity check, 0 element case has a specialization.
+
token_size_t I = 0; // Start indexing from position \c 0.
- O[0] = 0; // First offset is always \c 0.
+ Offsets[0] = 0; // First offset is always \c 0; correctly aligned.
while (I < N - 1) {
- ASSERT((size_t)I + 1 < O.size() && lengthOfToken(T) == N - I);
+ ASSERT((size_t)I + 1 < Offsets.size() && lengthOfToken(T) == N - I);
// Calculate next offset based on the previous one.
- // \note The offset of the last value is stored at `O[N - 1]`, which is
- // set when `I == N - 2`. Hence the limit of the loop.
- O[I + 1] = O[I] + sizeOfHeadOfToken(T);
+ // \note The offset of the last value is stored at `O[N - 1]`, which
+ // is set when `I == N - 2`. Hence the limit of the loop.
+
+ const auto LastOffset = Offsets[I];
+ auto &Offset = Offsets[++I];
+
+ const auto LastSize = sizeOfHeadOfToken(T);
dropHeadOfToken(T);
- ++I;
+ const auto CurrentAlign = alignmentOfHeadOfToken(T);
+
+ Offset = LastOffset + LastSize;
+ Offset += CurrentAlign - 1;
+ Offset &= -std::make_signed_t<decltype(CurrentAlign)>(CurrentAlign);
}
- ASSERT((size_t)I + 1 == O.size() && lengthOfToken(T) == 1);
+ ASSERT((size_t)I + 1 == Offsets.size() && lengthOfToken(T) == 1);
}
- return O;
+ return Offsets;
}
+ /// Tells the size of \c rosa::TokenizedStorage::Arena.
+ ///
+ /// \note Alignment requirement of each value is taken into account.
+ ///
+ /// \return size of \c rosa::TokenizedStorage::Arena to store values
+ static size_t arenaSize(void) noexcept {
+ static size_t ArenaSize = 0;
+ // Initialize ArenaSize during first invocation.
+ if (!ArenaSize) {
+ const auto &Offsets = offsets();
+ Token T = ST;
+ const auto N = lengthOfToken(T);
+ dropNOfToken(T, N - 1); // Get to the last type
+ // Full size is the offset for plus the size of the last value.
+ ArenaSize = Offsets[N - 1] + sizeOfHeadOfToken(T);
+ }
+ return ArenaSize;
+ }
+
+private:
+ /// A BLOB storing all the values one after the other with necessary padding
+ /// for correct alignment.
+ void *const Arena;
+
public:
/// Creates an instance with default values.
///
/// \note This constructor requires that all actual template arguments \p
/// Types... are default constructible.
TokenizedStorage(void) noexcept
- : Arena(::operator new(sizeOfValuesOfToken(ST))) {
+ : Arena(::operator new(arenaSize())) {
ASSERT(Arena != nullptr); // Sanity check.
createArenaElements(Arena, Types()...);
}
/// Creates an instance from constant lvalue references.
///
/// \param Ts values to store
TokenizedStorage(const std::decay_t<Types> &... Ts) noexcept
- : Arena(::operator new(sizeOfValuesOfToken(ST))) {
+ : Arena(::operator new(arenaSize())) {
ASSERT(Arena != nullptr); // Sanity check.
createArenaElements(Arena, Ts...);
}
/// Creates an instance from rvalue references.
///
/// \param Ts values to store
TokenizedStorage(std::decay_t<Types> &&... Ts) noexcept
- : Arena(::operator new(sizeOfValuesOfToken(ST))) {
+ : Arena(::operator new(arenaSize())) {
ASSERT(Arena != nullptr); // Sanity check.
createArenaElements(Arena, std::move(Ts)...);
}
/// No copying and moving of \c rosa::TokenizedStorage instances.
///
/// \note This restriction may be relaxed as moving should be easy to
/// implement, only requires the possiblity to validate Arena pointer.
///@{
TokenizedStorage(const TokenizedStorage &) = delete;
TokenizedStorage &operator=(const TokenizedStorage &) = delete;
TokenizedStorage(TokenizedStorage &&Other) = delete;
TokenizedStorage &operator=(TokenizedStorage &&) = delete;
///@}
// Destroys \p this object.
~TokenizedStorage(void) {
destroyArenaElements<std::decay_t<Types>...>(Arena);
::operator delete(Arena);
}
/// Tells how many values are stored in \p this object.
///
/// \return number of values stored in \p this object
- size_t size(void) const noexcept override { return Offsets.size(); }
+ size_t size(void) const noexcept override { return offsets().size(); }
/// Tells the type of the value stored at a position.
///
/// \param Pos the index of the value whose type is to returned
///
/// \return \c rosa::TypeNumber for the value stored at index \p Pos
///
/// \pre \p Pos is a valid index:\code
/// Pos < size()
/// \endcode
TypeNumber typeAt(const token_size_t Pos) const noexcept override {
ASSERT(Pos < size());
Token TT = ST;
dropNOfToken(TT, Pos);
return headOfToken(TT);
}
/// Provides an untyped pointer for the value stored at a position.
///
/// \param Pos the index of the value to return an untyped pointer for
///
/// \return untyped pointer for the value stored at index \p Pos
///
/// \pre \p Pos is a valid index:\code
/// Pos < size()
/// \endcode
void *pointerTo(const token_size_t Pos) noexcept override {
ASSERT(Pos < size());
- return static_cast<uint8_t *>(Arena) + Offsets[Pos];
+ return static_cast<uint8_t *>(Arena) + offsets()[Pos];
}
/// Provides a constant untyped pointer for the value stored at a position.
///
/// \param Pos the index of the value to return an untyped pointer for
///
/// \return constant untyped pointer for the value stored at index \p Pos
///
/// \pre \p Pos is a valid index:\code
- /// Pos < Offsets.size()
+ /// Pos < size()
/// \endcode
const void *pointerTo(const token_size_t Pos) const noexcept override {
ASSERT(Pos < size());
- return static_cast<const uint8_t *>(Arena) + Offsets[Pos];
+ return static_cast<const uint8_t *>(Arena) + offsets()[Pos];
}
/// Tells if the value stored at a given index is of a given type.
///
/// \note Any \c rosa::AtomConstant is encoded in \c rosa::Token as
/// the \c rosa::AtomValue wrapped into it.
///
/// \tparam T type to match against
///
/// \param Pos index the type of the value at is to be matched against \p Type
///
/// \return if the value at index \p Pos of type \p T
///
/// \pre \p Pos is a valid index:\code
- /// Pos < Offsets.size()
+ /// Pos < size()
/// \endcode
template <typename T> bool isTypeAt(const size_t Pos) const noexcept {
ASSERT(Pos < size());
Token TT = ST;
dropNOfToken(TT, Pos);
return isHeadOfTokenTheSameType<T>(TT);
}
/// Gives a reference of a value of a given type stored at a given index.
///
/// \note The constant variant of the function relies on this implementation,
/// the function may not modify \p this object!
///
/// \tparam T type to give a reference of
///
/// \param Pos index to set the reference for
///
/// \return reference of \p T for the value stored at index \p Pos
///
/// \pre \p Pos is a valid index and the value at index \p Pos is of type
/// \p T:
/// \code
/// Pos < Size && isTypeAt<T>(Pos)
/// \endcode
template <typename T> T &valueAt(const token_size_t Pos) noexcept {
ASSERT(Pos < size() && isTypeAt<T>(Pos));
return *static_cast<T *>(pointerTo(Pos));
}
/// Gives a constant reference of a value of a given type stored at a given
/// index.
///
/// \tparam T type to give a reference of
///
/// \param Pos index to set the reference for
///
/// \return constant reference of \p T for the value stored at index \p Pos
///
/// \pre \p Pos is a valid index and the value at index \p Pos is of type
/// \p T:
/// \code
/// Pos < Size && isTypeAt<T>(Pos)
/// \endcode
template <typename T>
const T &valueAt(const token_size_t Pos) const noexcept {
// \note Just use the non-const implementation as that does not modify
// \p this object.
return const_cast<TokenizedStorage *>(this)->valueAt<T>(Pos);
}
};
-// Implementation of the static member field \c rosa::TokenizedStorage::Offsets.
-template <typename... Types>
-const std::vector<size_t>
- TokenizedStorage<Types...>::Offsets = TokenizedStorage<Types...>::offsets();
-
/// Specialization of the template \c rosa::TokenizedStorage for storing
/// nothing.
///
/// \note The specialization implements the interface defined by \c
/// rosa::AbstractTokenizedStorage but most of the functions cannot be called
/// because nothing is stored in instances of the class.
template <> class TokenizedStorage<> : public AbstractTokenizedStorage {
public:
/// \c rosa::Token for the stored values.
static constexpr Token ST = TypeToken<>::Value;
- /// Byte offsets to access stored values in \c rosa::TokenizedStorage::Arena.
- static const std::vector<size_t> Offsets;
-
/// Creates an instance.
TokenizedStorage(void) noexcept = default;
/// No copying and moving of \c rosa::TokenizedStorage instances.
///
/// \note This restriction may be relaxed as moving should be easy to
/// implement, only requires the possiblity to validate Arena pointer.
///@{
TokenizedStorage(const TokenizedStorage &) = delete;
TokenizedStorage &operator=(const TokenizedStorage &) = delete;
TokenizedStorage(TokenizedStorage &&Other) = delete;
TokenizedStorage &operator=(TokenizedStorage &&) = delete;
///@}
// Destroys \p this object.
~TokenizedStorage(void) override {}
/// Tells how many values are stored in \p this object.
///
/// \return `0`
size_t size(void) const noexcept override { return 0; }
/// Tells the type of the value stored at a position.
///
/// \pre Do not call.
TypeNumber typeAt(const token_size_t) const noexcept override {
LOG_ERROR("Called unsupported function");
return TypeNumber(0);
}
/// Provides an untyped pointer for the value stored at a position.
///
/// \pre Do not call.
void *pointerTo(const token_size_t) noexcept override {
LOG_ERROR("Called unsupported function");
return nullptr;
}
/// Provides a constant untyped pointer for the value stored at a position.
///
/// \pre Do not call.
const void *pointerTo(const token_size_t) const noexcept override {
LOG_ERROR("Called unsupported function");
return nullptr;
}
/// Tells if the value stored at a given index is of a given type.
///
/// \pre Do not call.
template <typename> bool isTypeAt(const size_t) const noexcept {
LOG_ERROR("Called unsupported function");
return false;
}
/// Gives a reference of a value of a given type stored at a given index.
///
/// \tparam T type to give a reference of
/// \pre Do not call.
template <typename T> T &valueAt(const token_size_t) noexcept {
LOG_ERROR("Called unsupported function");
return *static_cast<T *>(nullptr);
}
/// Gives a constant reference of a value of a given type stored at a given
/// index.
///
/// \tparam T type to give a reference of
///
/// \pre Do not call.
template <typename T> const T &valueAt(const token_size_t) const noexcept {
LOG_ERROR("Called unsupported function");
// \note Just use the non-const implementation as that does not modify
// \p this object.
return *static_cast<T *>(nullptr);
}
};
} // End namespace rosa
#endif // ROSA_SUPPORT_TOKENIZED_STORAGES_HPP
diff --git a/include/rosa/support/type_numbers.hpp b/include/rosa/support/type_numbers.hpp
index 024b147..82c516a 100644
--- a/include/rosa/support/type_numbers.hpp
+++ b/include/rosa/support/type_numbers.hpp
@@ -1,245 +1,248 @@
//===-- rosa/support/type_numbers.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_numbers.hpp
///
/// \author David Juhasz (david.juhasz@tuwien.ac.at)
///
-/// \date 2017-2019
+/// \date 2017-2020
///
/// \brief Facilities for registering supported types and representing them with
/// numbers.
///
/// \note This implementation is partially based on the \c type_number
/// implementation of CAF.
///
//===----------------------------------------------------------------------===//
#ifndef ROSA_SUPPORT_TYPE_NUMBERS_HPP
#define ROSA_SUPPORT_TYPE_NUMBERS_HPP
#include "rosa/support/atom.hpp"
#include "rosa/support/math.hpp"
#include "rosa/support/squashed_int.hpp"
#include "rosa/support/type_helper.hpp"
#include "rosa/support/types.hpp"
#include <array>
#include <string>
namespace rosa {
/// Compile-time list of all built-in types.
/// \note Appending new types to the end of this list maintains backward
/// compatibility in the sense that old builtin types have the same type number
/// associated to them in both the old and new versions. But changing any of
/// the already present types in the list breaks that backward compatibility.
/// Should compatibility be broken, step \c rosa::TypeNumberVersion below!
/// \note Keep this list in sync with the definition of
/// \c rosa::NumberedTypeNames.
/// \note The built-in types are explicitly listed in the definition of
/// rosa::app::AppAgent. Keep those definitions in sync with this list.
using BuiltinTypes = TypeList<AtomValue, ///< atom
int16_t, ///< i16
int32_t, ///< i32
int64_t, ///< i64
int8_t, ///< i8
long double, ///< ldouble
std::string, ///< str
uint16_t, ///< u16
uint32_t, ///< u32
uint64_t, ///< u64
uint8_t, ///< u8
unit_t, ///< unit
bool, ///< bool
double, ///< double
float ///< float
>;
/// Indicates the version number of \c rosa::BuiltinTypes.
///
/// Software with the same version number are supposed to have backward
/// compatible type numbering.
///
/// \sa \c rosa::BultinTypes on backward compatibility.
constexpr size_t TypeNumberVersion = 0;
/// The number of built-in types.
static constexpr size_t NumberOfBuiltinTypes =
TypeListSize<BuiltinTypes>::Value;
/// Anonymous namespace for helper facilities, consider it private.
namespace {
/// Tells if a type is not \c rosa::NoneType.
///
/// \tparam T the type to check
template <typename T> struct IsNotNoneType {
/// Denotes if \p T is the \c rosa::NoneType or not.
static constexpr bool Value = !std::is_same<T, NoneType>::value;
};
} // End namespace
/// Integer type to store type numbers.
/// \note The narrowest unsigned integer type that is wide enough to represent
/// \c NumberOfBuiltinTypes different values.
using type_nr_t = typename TypeListFind<
typename TypeListDrop<log2(NumberOfBuiltinTypes) / 8 + 1,
IntegerTypesBySize>::Type,
IsNotNoneType>::Type::Second;
/// Turn \c rosa::type_nr_t into a strongly typed enumeration.
///
/// Values of \c rosa::type_nr_t casted to \c rosa::TypeNumbers can be used in a
/// type-safe way.
enum class TypeNumber : type_nr_t {};
/// A type to cast type numbers 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_tn_t = printable_t<type_nr_t>;
/// Casts a \c rosa::TypeNumber into \c rosa::printable_tn_t.
///
/// \param TN \c rosa::TypeNumber to cast.
#define PRINTABLE_TN(TN) static_cast<printable_tn_t>(TN)
/// \name TypeNumberOf
/// \brief Computes \c rosa::TypeNumber for a type.
///
/// The \c rosa::TypeNumber for a type \c T can be obtained as \code
/// TypeNumberOf<T>::Value
/// \endcode
///
/// \note \c rosa::TypeNumber for a type is based on the corresponding squashed
/// type, except for \c rosa::AtomConstant types.
///
/// \sa \c rosa::SquashedType
///
/// \note \c rosa::TypeNumber is the index of the type in \c rosa::BuiltinTypes
/// starting from \c 1; index \c 0 indicates a non-builtin type.
///@{
/// Definition of the template for the general case.
///
/// \tparam T type to get \c rosa::TypeNumber for
template <typename T> struct TypeNumberOf {
static constexpr TypeNumber Value = static_cast<TypeNumber>(
TypeListIndexOf<BuiltinTypes, squashed_t<T>>::Value + 1);
};
/// Specialization for \c rosa::AtomConstant.
///
/// \note For a \c rosa::AtomConstant type, \c rosa::TypeNumber is based on the
/// \c rosa::AtomValue wrapped into the actual \c rosa::AtomConstant.
template <AtomValue V> struct TypeNumberOf<AtomConstant<V>> {
static constexpr TypeNumber Value = TypeNumberOf<AtomValue>::Value;
};
///@}
// clang-format off
/// List of type names for all builtin-types, indexed via \c rosa::TypeNumber.
///
/// \note Keep this definition in sync with \c rosa::BuiltinTypes.
constexpr std::array<const char *, NumberOfBuiltinTypes> NumberedTypeNames {{
"atom",
"i16",
"i32",
"i64",
"i8",
"ldouble",
"str",
"u16",
"u32",
"u64",
"u8",
"unit",
"bool",
"double",
"float"
}};
// clang-format on
/// Tells if a \c rosa::TypeNumber is valid in the software.
///
/// \note A \c rosa::TypeNumber generated by an incompatible version may be
/// valid but may denote a type that is different from the \c rosa::TypeNumber
/// denotes in the current software. That is why this validation needs to be
/// done in connection to checking \c rosa::TypeNumberVersion as well.
///
/// \param TN \c rosa::TypeNumber to validate in the context of the current
/// software
///
/// \return Whether \p TN is valid in the current software
constexpr bool validTypeNumber(const TypeNumber TN) {
// \todo Duplication of static_cast into a const variable would be
// possible in C++14.
return 0 < static_cast<type_nr_t>(TN) &&
static_cast<type_nr_t>(TN) <= NumberOfBuiltinTypes;
}
/// Provides information about the type corresponding to a \c rosa::TypeNumber.
///
/// \tparam TN \c rosa::TypeNumber to get information for
///
/// \pre Statically, \p TN is a valid \c rosa::TypeNumber:
/// \code
/// validTypeNumber(TN)
/// \endcode
template <TypeNumber TN> struct TypeForNumber {
STATIC_ASSERT(validTypeNumber(TN), "not a valid type number");
/// \p TN as \c rosa::type_nr_t.
static constexpr type_nr_t TNI = static_cast<type_nr_t>(TN);
/// The builtin-type corresponding to \p TN.
using Type = typename TypeListAt<BuiltinTypes, TNI - 1>::Type;
/// The size of \c Type.
static constexpr size_t Size = sizeof(Type);
+ /// The alignment of \c Type.
+ static constexpr size_t Align = alignof(Type);
+
/// Textual representation of the builtin-type.
static constexpr const char *Name = NumberedTypeNames[TNI - 1];
};
} // End namespace rosa
namespace std {
/// Converts a \c rosa::TypeNumber into \c std::string.
///
/// \param TN \c rosa::TypeNumber to convert
///
/// \return \c std::string representing \p TN
inline string to_string(const rosa::TypeNumber TN) {
return to_string(static_cast<rosa::type_nr_t>(TN));
}
/// Dumps a \c rosa::TypeNumber to a given \c std::ostream.
///
/// \param [in,out] OS output stream to dump to
/// \param TN \c rosa::TypeNumber to dump
///
/// \return \p OS after dumping \p TN to it
inline ostream &operator<<(ostream &OS, const rosa::TypeNumber &TN) {
OS << to_string(TN);
return OS;
}
} // End namespace std
#endif // ROSA_SUPPORT_TYPE_NUMBERS_HPP
diff --git a/include/rosa/support/type_token.hpp b/include/rosa/support/type_token.hpp
index 57a860c..f989b5a 100644
--- a/include/rosa/support/type_token.hpp
+++ b/include/rosa/support/type_token.hpp
@@ -1,327 +1,325 @@
//===-- 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-2019
+/// \date 2017-2020
///
/// \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);
+/// 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
diff --git a/lib/support/tokenized_storages.cpp b/lib/support/tokenized_storages.cpp
index 69d1ea8..37e929e 100755
--- a/lib/support/tokenized_storages.cpp
+++ b/lib/support/tokenized_storages.cpp
@@ -1,31 +1,23 @@
//===-- support/tokenized_storages.cpp --------------------------*- 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 support/tokenized_storages.cpp
///
/// \author David Juhasz (david.juhasz@tuwien.ac.at)
///
-/// \date 2017-2019
+/// \date 2017-2020
///
/// \brief Implementation of rosa/support/tokenized_storages.hpp.
///
//===----------------------------------------------------------------------===//
#include "rosa/support/tokenized_storages.hpp"
-
-namespace rosa {
-
-// Implementation of the static member field \c
-// rosa::TokenizedStorage<>::Offsets.
-const std::vector<size_t> TokenizedStorage<>::Offsets = std::vector<size_t>(0);
-
-} // End namespace rosa
\ No newline at end of file
diff --git a/lib/support/type_token.cpp b/lib/support/type_token.cpp
index 5a729bb..23513c6 100644
--- a/lib/support/type_token.cpp
+++ b/lib/support/type_token.cpp
@@ -1,137 +1,152 @@
//===-- support/type_token.cpp ----------------------------------*- 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 support/type_token.cpp
///
/// \author David Juhasz (david.juhasz@tuwien.ac.at)
///
-/// \date 2017-2019
+/// \date 2017-2020
///
/// \brief Implementation for rosa/support/type_token.hpp.
///
/// \todo Automatically generate proper cases for the switches with a big number
/// of handcrafted similar cases in them.
///
//===----------------------------------------------------------------------===//
#include "rosa/support/type_token.hpp"
namespace rosa {
using namespace token;
bool validToken(const Token T) {
Token TT = T;
bool Valid = true;
while (Valid && !emptyToken(TT)) {
Valid &= validTypeNumber(headOfToken(TT));
dropHeadOfToken(TT);
}
return Valid;
}
bool emptyToken(const Token T) { return static_cast<token_t>(T) == 0; }
token_size_t lengthOfToken(const Token T) {
Token TT = T;
token_size_t N = 0;
while (!emptyToken(TT)) {
++N;
dropHeadOfToken(TT);
}
return N;
}
-size_t sizeOfValuesOfToken(const Token T) {
- ASSERT(validToken(T));
- Token TT = T;
- size_t S = 0;
- while (!emptyToken(TT)) {
- S += sizeOfHeadOfToken(TT);
- dropHeadOfToken(TT);
- }
- return S;
-}
-
-#define SIZECASE(N) \
+#define TYPENUMBERCASE(N, FIELD)\
{ \
case N: \
- return TypeForNumber<static_cast<TypeNumber>(N)>::Size; \
+ return TypeForNumber<static_cast<TypeNumber>(N)>::FIELD; \
}
+#define SIZECASE(N) TYPENUMBERCASE(N, Size)
+
size_t sizeOfHeadOfToken(const Token T) {
ASSERT(!emptyToken(T) && validToken(T));
switch (static_cast<type_nr_t>(headOfToken(T))) {
default: {
// Should never come here when \p T is valid and the case-list below covers
// \c rosa::BuiltinTypes.
ROSA_CRITICAL("unknown type number");
}
SIZECASE(1);
SIZECASE(2);
SIZECASE(3);
SIZECASE(4);
SIZECASE(5);
SIZECASE(6);
SIZECASE(7);
SIZECASE(8);
SIZECASE(9);
SIZECASE(10);
SIZECASE(11);
SIZECASE(12);
SIZECASE(13);
SIZECASE(14);
SIZECASE(15);
}
}
-#define NAMECASE(N) \
- { \
- case N: \
- return TypeForNumber<static_cast<TypeNumber>(N)>::Name; \
+#define ALIGNCASE(N) TYPENUMBERCASE(N, Align)
+
+size_t alignmentOfHeadOfToken(const Token T) {
+ ASSERT(!emptyToken(T) && validToken(T));
+ switch (static_cast<type_nr_t>(headOfToken(T))) {
+ default: {
+ // Should never come here when \p T is valid and the case-list below covers
+ // \c rosa::BuiltinTypes.
+ ROSA_CRITICAL("unknown type number");
+ }
+ SIZECASE(1);
+ SIZECASE(2);
+ SIZECASE(3);
+ SIZECASE(4);
+ SIZECASE(5);
+ SIZECASE(6);
+ SIZECASE(7);
+ SIZECASE(8);
+ SIZECASE(9);
+ SIZECASE(10);
+ SIZECASE(11);
+ SIZECASE(12);
+ SIZECASE(13);
+ SIZECASE(14);
+ SIZECASE(15);
}
+}
+
+#define NAMECASE(N) TYPENUMBERCASE(N, Name)
const char *nameOfHeadOfToken(const Token T) {
ASSERT(!emptyToken(T) && validToken(T));
switch (static_cast<type_nr_t>(headOfToken(T))) {
default: {
// Should never come here when \p T is valid and the case-list below covers
// \c rosa::BuiltinTypes.
ROSA_CRITICAL("unknown type number");
}
NAMECASE(1);
NAMECASE(2);
NAMECASE(3);
NAMECASE(4);
NAMECASE(5);
NAMECASE(6);
NAMECASE(7);
NAMECASE(8);
NAMECASE(9);
NAMECASE(10);
NAMECASE(11);
NAMECASE(12);
NAMECASE(13);
NAMECASE(14);
NAMECASE(15);
}
}
void dropHeadOfToken(Token &T) {
T = static_cast<Token>(static_cast<token_t>(T) >> RepresentationBits);
}
void dropNOfToken(Token &T, const size_t N) {
T = static_cast<Token>(static_cast<token_t>(T) >> (N * RepresentationBits));
}
} // End namespace rosa
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Thu, Jul 3, 3:27 PM (5 h, 42 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
157271
Default Alt Text
(55 KB)
Attached To
Mode
R20 SoC_Rosa_repo
Attached
Detach File
Event Timeline
Log In to Comment