Skip to content

Commit

Permalink
Add ImmutableMapRef and ImmutableSetRef, which consolidate Immutable[…
Browse files Browse the repository at this point in the history
…Map,Set] and its Factory. This may eventually replace Immtuable[Map,Set].

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@139967 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
tkremenek committed Sep 16, 2011
1 parent f67e855 commit 166e053
Show file tree
Hide file tree
Showing 2 changed files with 286 additions and 0 deletions.
153 changes: 153 additions & 0 deletions include/llvm/ADT/ImmutableMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,159 @@ class ImmutableMap {
}
};

// NOTE: This will possibly become the new implementation of ImmutableMap some day.
template <typename KeyT, typename ValT,
typename ValInfo = ImutKeyValueInfo<KeyT,ValT> >
class ImmutableMapRef {
public:
typedef typename ValInfo::value_type value_type;
typedef typename ValInfo::value_type_ref value_type_ref;
typedef typename ValInfo::key_type key_type;
typedef typename ValInfo::key_type_ref key_type_ref;
typedef typename ValInfo::data_type data_type;
typedef typename ValInfo::data_type_ref data_type_ref;
typedef ImutAVLTree<ValInfo> TreeTy;
typedef typename TreeTy::Factory FactoryTy;

protected:
TreeTy *Root;
FactoryTy *Factory;

public:
/// Constructs a map from a pointer to a tree root. In general one
/// should use a Factory object to create maps instead of directly
/// invoking the constructor, but there are cases where make this
/// constructor public is useful.
explicit ImmutableMapRef(const TreeTy* R, FactoryTy *F)
: Root(const_cast<TreeTy*>(R)),
Factory(F) {
if (Root) { Root->retain(); }
}

ImmutableMapRef(const ImmutableMapRef &X)
: Root(X.Root),
Factory(X.Factory) {
if (Root) { Root->retain(); }
}

ImmutableMapRef &operator=(const ImmutableMapRef &X) {
if (Root != X.Root) {
if (X.Root)
X.Root->retain();

if (Root)
Root->release();

Root = X.Root;
Factory = X.Factory;
}
return *this;
}

~ImmutableMapRef() {
if (Root)
Root->release();
}

static inline ImmutableMapRef getEmptyMap(FactoryTy *F) {
return ImmutableMapRef(0, F);
}

ImmutableMapRef add(key_type_ref K, data_type_ref D) {
TreeTy *NewT = Factory->add(Root, std::pair<key_type, data_type>(K, D));
return ImmutableMapRef(NewT, Factory);
}

ImmutableMapRef remove(key_type_ref K) {
TreeTy *NewT = Factory->remove(Root, K);
return ImmutableMapRef(NewT, Factory);
}

bool contains(key_type_ref K) const {
return Root ? Root->contains(K) : false;
}

ImmutableMap<KeyT, ValT> asImmutableMap() const {
return ImmutableMap<KeyT, ValT>(Factory->getCanonicalTree(Root));
}

bool operator==(const ImmutableMapRef &RHS) const {
return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root;
}

bool operator!=(const ImmutableMapRef &RHS) const {
return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root;
}

bool isEmpty() const { return !Root; }

//===--------------------------------------------------===//
// For testing.
//===--------------------------------------------------===//

void verify() const { if (Root) Root->verify(); }

//===--------------------------------------------------===//
// Iterators.
//===--------------------------------------------------===//

class iterator {
typename TreeTy::iterator itr;

iterator() {}
iterator(TreeTy* t) : itr(t) {}
friend class ImmutableMapRef;

public:
value_type_ref operator*() const { return itr->getValue(); }
value_type* operator->() const { return &itr->getValue(); }

key_type_ref getKey() const { return itr->getValue().first; }
data_type_ref getData() const { return itr->getValue().second; }


iterator& operator++() { ++itr; return *this; }
iterator operator++(int) { iterator tmp(*this); ++itr; return tmp; }
iterator& operator--() { --itr; return *this; }
iterator operator--(int) { iterator tmp(*this); --itr; return tmp; }
bool operator==(const iterator& RHS) const { return RHS.itr == itr; }
bool operator!=(const iterator& RHS) const { return RHS.itr != itr; }
};

iterator begin() const { return iterator(Root); }
iterator end() const { return iterator(); }

data_type* lookup(key_type_ref K) const {
if (Root) {
TreeTy* T = Root->find(K);
if (T) return &T->getValue().second;
}

return 0;
}

/// getMaxElement - Returns the <key,value> pair in the ImmutableMap for
/// which key is the highest in the ordering of keys in the map. This
/// method returns NULL if the map is empty.
value_type* getMaxElement() const {
return Root ? &(Root->getMaxElement()->getValue()) : 0;
}

//===--------------------------------------------------===//
// Utility methods.
//===--------------------------------------------------===//

unsigned getHeight() const { return Root ? Root->getHeight() : 0; }

static inline void Profile(FoldingSetNodeID& ID, const ImmutableMapRef &M) {
ID.AddPointer(M.Root);
}

inline void Profile(FoldingSetNodeID& ID) const {
return Profile(ID, *this);
}
};

} // end namespace llvm

#endif
133 changes: 133 additions & 0 deletions include/llvm/ADT/ImmutableSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -997,6 +997,10 @@ class ImmutableSet {

BumpPtrAllocator& getAllocator() { return F.getAllocator(); }

typename TreeTy::Factory *getTreeFactory() const {
return const_cast<typename TreeTy::Factory *>(&F);
}

private:
Factory(const Factory& RHS); // DO NOT IMPLEMENT
void operator=(const Factory& RHS); // DO NOT IMPLEMENT
Expand All @@ -1021,6 +1025,10 @@ class ImmutableSet {
if (Root) { Root->retain(); }
return Root;
}

TreeTy *getRootWithoutRetain() const {
return Root;
}

/// isEmpty - Return true if the set contains no elements.
bool isEmpty() const { return !Root; }
Expand Down Expand Up @@ -1078,6 +1086,131 @@ class ImmutableSet {

void validateTree() const { if (Root) Root->validateTree(); }
};

// NOTE: This may some day replace the current ImmutableSet.
template <typename ValT, typename ValInfo = ImutContainerInfo<ValT> >
class ImmutableSetRef {
public:
typedef typename ValInfo::value_type value_type;
typedef typename ValInfo::value_type_ref value_type_ref;
typedef ImutAVLTree<ValInfo> TreeTy;
typedef typename TreeTy::Factory FactoryTy;

private:
TreeTy *Root;
FactoryTy *Factory;

public:
/// Constructs a set from a pointer to a tree root. In general one
/// should use a Factory object to create sets instead of directly
/// invoking the constructor, but there are cases where make this
/// constructor public is useful.
explicit ImmutableSetRef(TreeTy* R, FactoryTy *F)
: Root(R),
Factory(F) {
if (Root) { Root->retain(); }
}
ImmutableSetRef(const ImmutableSetRef &X)
: Root(X.Root),
Factory(X.Factory) {
if (Root) { Root->retain(); }
}
ImmutableSetRef &operator=(const ImmutableSetRef &X) {
if (Root != X.Root) {
if (X.Root) { X.Root->retain(); }
if (Root) { Root->release(); }
Root = X.Root;
Factory = X.Factory;
}
return *this;
}
~ImmutableSetRef() {
if (Root) { Root->release(); }
}

static inline ImmutableSetRef getEmptySet(FactoryTy *F) {
return ImmutableSetRef(0, F);
}

ImmutableSetRef add(value_type_ref V) {
return ImmutableSetRef(Factory->add(Root, V), Factory);
}

ImmutableSetRef remove(value_type_ref V) {
return ImmutableSetRef(Factory->remove(Root, V), Factory);
}

/// Returns true if the set contains the specified value.
bool contains(value_type_ref V) const {
return Root ? Root->contains(V) : false;
}

ImmutableSet<ValT> asImmutableSet() const {
return ImmutableSet<ValT>(Factory->getCanonicalTree(Root));
}

TreeTy *getRootWithoutRetain() const {
return Root;
}

bool operator==(const ImmutableSetRef &RHS) const {
return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root;
}

bool operator!=(const ImmutableSetRef &RHS) const {
return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root;
}

/// isEmpty - Return true if the set contains no elements.
bool isEmpty() const { return !Root; }

/// isSingleton - Return true if the set contains exactly one element.
/// This method runs in constant time.
bool isSingleton() const { return getHeight() == 1; }

//===--------------------------------------------------===//
// Iterators.
//===--------------------------------------------------===//

class iterator {
typename TreeTy::iterator itr;
iterator(TreeTy* t) : itr(t) {}
friend class ImmutableSetRef<ValT,ValInfo>;
public:
iterator() {}
inline value_type_ref operator*() const { return itr->getValue(); }
inline iterator& operator++() { ++itr; return *this; }
inline iterator operator++(int) { iterator tmp(*this); ++itr; return tmp; }
inline iterator& operator--() { --itr; return *this; }
inline iterator operator--(int) { iterator tmp(*this); --itr; return tmp; }
inline bool operator==(const iterator& RHS) const { return RHS.itr == itr; }
inline bool operator!=(const iterator& RHS) const { return RHS.itr != itr; }
inline value_type *operator->() const { return &(operator*()); }
};

iterator begin() const { return iterator(Root); }
iterator end() const { return iterator(); }

//===--------------------------------------------------===//
// Utility methods.
//===--------------------------------------------------===//

unsigned getHeight() const { return Root ? Root->getHeight() : 0; }

static inline void Profile(FoldingSetNodeID& ID, const ImmutableSetRef& S) {
ID.AddPointer(S.Root);
}

inline void Profile(FoldingSetNodeID& ID) const {
return Profile(ID,*this);
}

//===--------------------------------------------------===//
// For testing.
//===--------------------------------------------------===//

void validateTree() const { if (Root) Root->validateTree(); }
};

} // end namespace llvm

Expand Down

0 comments on commit 166e053

Please sign in to comment.