#ifndef LLVM_ADT_IMMUTABLEMAP_H
#define LLVM_ADT_IMMUTABLEMAP_H
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ImmutableSet.h"
#include "llvm/Support/Allocator.h"
#include <utility>
namespace llvm {
template <typename T, typename S>
struct ImutKeyValueInfo { … };
template <typename KeyT, typename ValT,
typename ValInfo = ImutKeyValueInfo<KeyT,ValT>>
class ImmutableMap {
public:
using value_type = typename ValInfo::value_type;
using value_type_ref = typename ValInfo::value_type_ref;
using key_type = typename ValInfo::key_type;
using key_type_ref = typename ValInfo::key_type_ref;
using data_type = typename ValInfo::data_type;
using data_type_ref = typename ValInfo::data_type_ref;
using TreeTy = ImutAVLTree<ValInfo>;
protected:
IntrusiveRefCntPtr<TreeTy> Root;
public:
explicit ImmutableMap(const TreeTy *R) : … { … }
class Factory {
typename TreeTy::Factory F;
const bool Canonicalize;
public:
Factory(bool canonicalize = true) : Canonicalize(canonicalize) {}
Factory(BumpPtrAllocator &Alloc, bool canonicalize = true)
: F(Alloc), Canonicalize(canonicalize) {}
Factory(const Factory &) = delete;
Factory &operator=(const Factory &) = delete;
ImmutableMap getEmptyMap() { return ImmutableMap(F.getEmptyTree()); }
[[nodiscard]] ImmutableMap add(ImmutableMap Old, key_type_ref K,
data_type_ref D) {
TreeTy *T = F.add(Old.Root.get(), std::pair<key_type, data_type>(K, D));
return ImmutableMap(Canonicalize ? F.getCanonicalTree(T): T);
}
[[nodiscard]] ImmutableMap remove(ImmutableMap Old, key_type_ref K) {
TreeTy *T = F.remove(Old.Root.get(), K);
return ImmutableMap(Canonicalize ? F.getCanonicalTree(T): T);
}
typename TreeTy::Factory *getTreeFactory() const {
return const_cast<typename TreeTy::Factory *>(&F);
}
};
bool contains(key_type_ref K) const { … }
bool operator==(const ImmutableMap &RHS) const { … }
bool operator!=(const ImmutableMap &RHS) const { … }
TreeTy *getRoot() const { … }
TreeTy *getRootWithoutRetain() const { … }
void manualRetain() { … }
void manualRelease() { … }
bool isEmpty() const { … }
public:
void verify() const { … }
class iterator : public ImutAVLValueIterator<ImmutableMap> {
friend class ImmutableMap;
iterator() = default;
explicit iterator(TreeTy *Tree) : iterator::ImutAVLValueIterator(Tree) {}
public:
key_type_ref getKey() const { return (*this)->first; }
data_type_ref getData() const { return (*this)->second; }
};
iterator begin() const { … }
iterator end() const { … }
data_type* lookup(key_type_ref K) const { … }
value_type* getMaxElement() const { … }
unsigned getHeight() const { … }
static inline void Profile(FoldingSetNodeID& ID, const ImmutableMap& M) { … }
inline void Profile(FoldingSetNodeID& ID) const { … }
};
template <typename KeyT, typename ValT,
typename ValInfo = ImutKeyValueInfo<KeyT,ValT>>
class ImmutableMapRef {
public:
using value_type = typename ValInfo::value_type;
using value_type_ref = typename ValInfo::value_type_ref;
using key_type = typename ValInfo::key_type;
using key_type_ref = typename ValInfo::key_type_ref;
using data_type = typename ValInfo::data_type;
using data_type_ref = typename ValInfo::data_type_ref;
using TreeTy = ImutAVLTree<ValInfo>;
using FactoryTy = typename TreeTy::Factory;
protected:
IntrusiveRefCntPtr<TreeTy> Root;
FactoryTy *Factory;
public:
ImmutableMapRef(const TreeTy *R, FactoryTy *F)
: … { … }
ImmutableMapRef(const ImmutableMap<KeyT, ValT> &X,
typename ImmutableMap<KeyT, ValT>::Factory &F)
: … { … }
static inline ImmutableMapRef getEmptyMap(FactoryTy *F) { … }
void manualRetain() { … }
void manualRelease() { … }
ImmutableMapRef add(key_type_ref K, data_type_ref D) const { … }
ImmutableMapRef remove(key_type_ref K) const { … }
bool contains(key_type_ref K) const { … }
ImmutableMap<KeyT, ValT> asImmutableMap() const { … }
bool operator==(const ImmutableMapRef &RHS) const { … }
bool operator!=(const ImmutableMapRef &RHS) const { … }
bool isEmpty() const { … }
void verify() const { … }
class iterator : public ImutAVLValueIterator<ImmutableMapRef> {
friend class ImmutableMapRef;
iterator() = default;
explicit iterator(TreeTy *Tree) : iterator::ImutAVLValueIterator(Tree) {}
public:
key_type_ref getKey() const { return (*this)->first; }
data_type_ref getData() const { return (*this)->second; }
};
iterator begin() const { … }
iterator end() const { … }
data_type *lookup(key_type_ref K) const { … }
value_type* getMaxElement() const { … }
unsigned getHeight() const { … }
static inline void Profile(FoldingSetNodeID &ID, const ImmutableMapRef &M) { … }
inline void Profile(FoldingSetNodeID &ID) const { … }
};
}
#endif