mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
49287e9de7
This commit: * Drops `KeyTraits::toString`: if needed, use `getNameFromYAMLScalar`. * Makes many methods in TupleTree.h return `nullptr` or `std::optional` in order to gracefully handle failures. * Provides `KeyTraits` specializations for integral types and tuple-like composed by types providing `KeyTraits`. * Introduces `CompositeScalar`, which enables tuple-like objects to be YAML-serializable scalars by joining the YAML-serialization of its members through a customziable character. * Implements `PathMatcher`, a very simple "regular expression" mechanism for paths on tuple trees. * Introduce testing for the Model.
123 lines
3.3 KiB
C++
123 lines
3.3 KiB
C++
#pragma once
|
|
|
|
//
|
|
// This file is distributed under the MIT License. See LICENSE.md for details.
|
|
//
|
|
|
|
#include "llvm/ADT/Twine.h"
|
|
|
|
#include "revng/ADT/STLExtras.h"
|
|
|
|
//
|
|
// KeyTraits
|
|
//
|
|
using KeyInt = uint64_t;
|
|
using KeyIntVector = std::vector<KeyInt>;
|
|
|
|
template<typename T, typename = void>
|
|
struct KeyTraits {
|
|
// static constexpr size_t IntsCount = ...;
|
|
// using IntsArray = std::array<KeyInt, IntsCount>;
|
|
//
|
|
// static T fromInts(const IntsArray &KeyAsInts) {
|
|
// ...
|
|
// }
|
|
//
|
|
// static IntsArray toInts(const T &I) {
|
|
// ...
|
|
// }
|
|
};
|
|
|
|
/// Trivial specialization for integral types
|
|
template<typename T>
|
|
struct KeyTraits<T, enable_if_is_integral_t<T>> {
|
|
static constexpr size_t IntsCount = 1;
|
|
using IntsArray = std::array<KeyInt, IntsCount>;
|
|
|
|
static T fromInts(const IntsArray &KeyAsInts) { return KeyAsInts[0]; }
|
|
|
|
static IntsArray toInts(const T &I) { return { static_cast<KeyInt>(I) }; }
|
|
};
|
|
|
|
template<typename T, typename K = void>
|
|
using enable_if_is_enum_t = std::enable_if_t<std::is_enum_v<T>, K>;
|
|
|
|
/// Trivial specialization for integral types
|
|
template<typename T>
|
|
struct KeyTraits<T, enable_if_is_enum_t<T>> {
|
|
static constexpr size_t IntsCount = 1;
|
|
using IntsArray = std::array<KeyInt, IntsCount>;
|
|
|
|
static T fromInts(const IntsArray &KeyAsInts) {
|
|
return static_cast<T>(KeyAsInts[0]);
|
|
}
|
|
|
|
static IntsArray toInts(const T &I) { return { static_cast<KeyInt>(I) }; }
|
|
};
|
|
|
|
//
|
|
// Derive KeyTraits from tuple-like of objects featuring KeyTraits
|
|
//
|
|
template<typename T>
|
|
struct KeyTraits<T, std::enable_if_t<std::tuple_size<T>::value >= 0>> {
|
|
private:
|
|
template<size_t I = 0>
|
|
static constexpr size_t computeIntsCount() {
|
|
if constexpr (I != std::tuple_size_v<T>) {
|
|
auto Result = KeyTraits<std::tuple_element_t<I, T>>::IntsCount;
|
|
return Result + computeIntsCount<I + 1>();
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
public:
|
|
static constexpr size_t IntsCount = KeyTraits::computeIntsCount();
|
|
using IntsArray = std::array<KeyInt, IntsCount>;
|
|
|
|
template<size_t I = 0, size_t First = 0>
|
|
constexpr static void populateKeyArray(IntsArray &Result, const T &Object) {
|
|
if constexpr (I != std::tuple_size_v<T>) {
|
|
using InnerKeyTraits = KeyTraits<std::tuple_element_t<I, T>>;
|
|
constexpr auto Size = InnerKeyTraits::IntsCount;
|
|
|
|
const auto &TupleEntry = InnerKeyTraits::toInts(get<I>(Object));
|
|
for (size_t J = 0; J < Size; ++J)
|
|
Result[First + J] = TupleEntry[J];
|
|
|
|
KeyTraits::populateKeyArray<I + 1, First + Size>(Result, Object);
|
|
}
|
|
}
|
|
|
|
static IntsArray toInts(const T &Object) {
|
|
IntsArray Result{};
|
|
KeyTraits::populateKeyArray(Result, Object);
|
|
return Result;
|
|
}
|
|
|
|
template<size_t I = 0, size_t First = 0>
|
|
constexpr static void setFields(T &Object, const IntsArray &Key) {
|
|
if constexpr (I != std::tuple_size_v<T>) {
|
|
using KeyTraits = KeyTraits<std::tuple_element_t<I, T>>;
|
|
|
|
// Populate partial key
|
|
constexpr auto Size = KeyTraits::IntsCount;
|
|
std::array<KeyInt, Size> PartialKey;
|
|
for (size_t J = 0; J < Size; ++J)
|
|
PartialKey[J] = Key[First + J];
|
|
|
|
// Create and fill the fields
|
|
get<I>(Object) = KeyTraits::fromInts(PartialKey);
|
|
|
|
// Recur
|
|
setFields<I + 1, First + Size>(Object, Key);
|
|
}
|
|
}
|
|
|
|
static T fromInts(const IntsArray &Key) {
|
|
T Result;
|
|
setFields(Result, Key);
|
|
return Result;
|
|
}
|
|
};
|