#pragma once // // This file is distributed under the MIT License. See LICENSE.md for details. // #include #include #include "llvm/Support/YAMLTraits.h" #include "revng/ADT/KeyedObjectTraits.h" #include "revng/ADT/STLExtras.h" #include "revng/ADT/UpcastablePointer.h" #include "revng/Support/Assert.h" template using KOTKey = decltype(KeyedObjectTraits::key(std::declval())); template using KOTCompare = std::less>; template> class MutableSet; template> class SortedVector; // // IsKeyedObjectContainer // namespace revng::detail { template concept IsMutableSet = is_specialization_v; template concept IsSortedVector = is_specialization_v; template concept IsKOC = IsMutableSet or IsSortedVector; } // namespace revng::detail template concept IsKeyedObjectContainer = revng::detail::IsKOC; static_assert(IsKeyedObjectContainer>); static_assert(IsKeyedObjectContainer>); template struct llvm::yaml::SequenceTraits { static size_t size(IO &TheIO, T &Seq) { return Seq.size(); } class Inserter { private: using value_type = typename T::value_type; using KOT = KeyedObjectTraits; using key_type = decltype(KOT::key(std::declval())); private: T &Seq; decltype(Seq.begin()) It; bool IsOutputting; std::optional BatchInserter; value_type Instance; unsigned Index = 0; public: Inserter(IO &TheIO, T &Seq) : Seq(Seq), It(Seq.begin()), IsOutputting(TheIO.outputting()), Instance(KOT::fromKey(key_type())) { if constexpr (std::is_const_v) { revng_assert(IsOutputting); } else { if (not IsOutputting) BatchInserter.emplace(std::move(Seq.batch_insert())); } } decltype(*It) &preflightElement(unsigned I) { revng_assert(Index == I); ++Index; if (IsOutputting) return *(It++); else return Instance; } void postflightElement(unsigned) { if (not IsOutputting) { BatchInserter->insert(Instance); Instance = KOT::fromKey(key_type()); } }; }; }; // // Iterable // template concept Iterable = requires { // * begin/end // * operator!= std::begin(std::declval()) != std::end(std::declval()); // * operator++ ++std::declval())) &>(); // * operator* void(*std::begin(std::declval())); }; static_assert(Iterable>); static_assert(not Iterable); // // StringLike // template concept HasCStr = std::is_same_v().c_str()), const char *>; static_assert(HasCStr>); static_assert(not HasCStr); template concept StringLike = std::is_convertible_v or HasCStr; static_assert(StringLike>); static_assert(StringLike); static_assert(not StringLike>); static_assert(StringLike); // // IsContainer // template concept IsContainer = Iterable and not StringLike; static_assert(IsContainer>); static_assert(IsContainer>); static_assert(IsContainer>); static_assert(IsContainer>); static_assert(!IsContainer); static_assert(!IsContainer>); static_assert(!IsContainer); // // SortedContainer and UnsortedContainer // // TODO: this is not very nice namespace revng::detail { template concept IsSet = is_specialization_v; } // namespace revng::detail template concept SortedContainer = revng::detail::IsSet or IsKeyedObjectContainer; template concept UnsortedContainer = IsContainer and not SortedContainer;