#pragma once // // This file is distributed under the MIT License. See LICENSE.md for details. // #include "revng/TupleTree/TupleTreeDiff.h" #include "revng/TupleTree/Visits.h" // // getByPath // namespace tupletree::detail { template struct GetByPathVisitor { ExpectedType *Result = nullptr; template void visitTupleElement(ExpectedType &Element) { Result = ∈ } template void visitTupleElement(AnyOtherType &) { Result = nullptr; } template void visitPolymorphicElement(Kind, ExpectedType &Element) { Result = ∈ } template void visitPolymorphicElement(Kind, AnyOtherType &) { Result = nullptr; } template void visitContainerElement(KeyT, ExpectedType &Element) { Result = ∈ } template void visitContainerElement(KeyT, AnyOtherType &) { Result = nullptr; } }; } // namespace tupletree::detail template tupletree::detail::getByPathRV * getByPath(const TupleTreePath &Path, RootT &M) { using namespace tupletree::detail; GetByPathVisitor> GBPV; if (not callByPath(GBPV, Path, M)) { return nullptr; } return GBPV.Result; } // // setByPath // template bool setByPath(const TupleTreePath &Path, RootT &M, const AllowedTupleTreeTypes &Value) { auto Visitor = [&Path, &M](const T &ActualValue) { T *ValueInM = getByPath(Path, M); if (ValueInM == nullptr) return false; *ValueInM = ActualValue; return true; }; return std::visit(Visitor, Value); } // // stringAsPath // template std::optional stringAsPath(llvm::StringRef Path) { if (Path.empty()) return std::nullopt; auto Result = PathMatcher::create(Path); if (not Result.has_value()) return std::nullopt; return Result->path(); } // // PathMatcher // template std::optional PathMatcher::create(llvm::StringRef Path) { PathMatcher Result; revng_assert(Path.startswith("/")); if (visitTupleTreeNode(Path.substr(1), Result)) return Result; else return {}; } template std::optional pathAsString(const TupleTreePath &Path) { std::string Result; { tupletree::detail::DumpPathVisitor PV(Result); if (not callOnPathSteps(PV, Path.toArrayRef())) { return {}; } } return Result; }