LLVM API Documentation
00001 //===--- ImmutableSet.h - Immutable (functional) set interface --*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines the ImutAVLTree and ImmutableSet classes. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #ifndef LLVM_ADT_IMSET_H 00015 #define LLVM_ADT_IMSET_H 00016 00017 #include "llvm/Support/Allocator.h" 00018 #include "llvm/ADT/FoldingSet.h" 00019 #include "llvm/Support/DataTypes.h" 00020 #include <cassert> 00021 #include <functional> 00022 00023 namespace llvm { 00024 00025 //===----------------------------------------------------------------------===// 00026 // Immutable AVL-Tree Definition. 00027 //===----------------------------------------------------------------------===// 00028 00029 template <typename ImutInfo> class ImutAVLFactory; 00030 template <typename ImutInfo> class ImutAVLTreeInOrderIterator; 00031 template <typename ImutInfo> class ImutAVLTreeGenericIterator; 00032 00033 template <typename ImutInfo > 00034 class ImutAVLTree : public FoldingSetNode { 00035 public: 00036 typedef typename ImutInfo::key_type_ref key_type_ref; 00037 typedef typename ImutInfo::value_type value_type; 00038 typedef typename ImutInfo::value_type_ref value_type_ref; 00039 00040 typedef ImutAVLFactory<ImutInfo> Factory; 00041 friend class ImutAVLFactory<ImutInfo>; 00042 00043 friend class ImutAVLTreeGenericIterator<ImutInfo>; 00044 friend class FoldingSet<ImutAVLTree>; 00045 00046 typedef ImutAVLTreeInOrderIterator<ImutInfo> iterator; 00047 00048 //===----------------------------------------------------===// 00049 // Public Interface. 00050 //===----------------------------------------------------===// 00051 00052 /// getLeft - Returns a pointer to the left subtree. This value 00053 /// is NULL if there is no left subtree. 00054 ImutAVLTree* getLeft() const { 00055 assert (!isMutable() && "Node is incorrectly marked mutable."); 00056 00057 return reinterpret_cast<ImutAVLTree*>(Left); 00058 } 00059 00060 /// getRight - Returns a pointer to the right subtree. This value is 00061 /// NULL if there is no right subtree. 00062 ImutAVLTree* getRight() const { return Right; } 00063 00064 00065 /// getHeight - Returns the height of the tree. A tree with no subtrees 00066 /// has a height of 1. 00067 unsigned getHeight() const { return Height; } 00068 00069 /// getValue - Returns the data value associated with the tree node. 00070 const value_type& getValue() const { return Value; } 00071 00072 /// find - Finds the subtree associated with the specified key value. 00073 /// This method returns NULL if no matching subtree is found. 00074 ImutAVLTree* find(key_type_ref K) { 00075 ImutAVLTree *T = this; 00076 00077 while (T) { 00078 key_type_ref CurrentKey = ImutInfo::KeyOfValue(T->getValue()); 00079 00080 if (ImutInfo::isEqual(K,CurrentKey)) 00081 return T; 00082 else if (ImutInfo::isLess(K,CurrentKey)) 00083 T = T->getLeft(); 00084 else 00085 T = T->getRight(); 00086 } 00087 00088 return NULL; 00089 } 00090 00091 /// size - Returns the number of nodes in the tree, which includes 00092 /// both leaves and non-leaf nodes. 00093 unsigned size() const { 00094 unsigned n = 1; 00095 00096 if (const ImutAVLTree* L = getLeft()) n += L->size(); 00097 if (const ImutAVLTree* R = getRight()) n += R->size(); 00098 00099 return n; 00100 } 00101 00102 /// begin - Returns an iterator that iterates over the nodes of the tree 00103 /// in an inorder traversal. The returned iterator thus refers to the 00104 /// the tree node with the minimum data element. 00105 iterator begin() const { return iterator(this); } 00106 00107 /// end - Returns an iterator for the tree that denotes the end of an 00108 /// inorder traversal. 00109 iterator end() const { return iterator(); } 00110 00111 bool ElementEqual(value_type_ref V) const { 00112 // Compare the keys. 00113 if (!ImutInfo::isEqual(ImutInfo::KeyOfValue(getValue()), 00114 ImutInfo::KeyOfValue(V))) 00115 return false; 00116 00117 // Also compare the data values. 00118 if (!ImutInfo::isDataEqual(ImutInfo::DataOfValue(getValue()), 00119 ImutInfo::DataOfValue(V))) 00120 return false; 00121 00122 return true; 00123 } 00124 00125 bool ElementEqual(const ImutAVLTree* RHS) const { 00126 return ElementEqual(RHS->getValue()); 00127 } 00128 00129 /// isEqual - Compares two trees for structural equality and returns true 00130 /// if they are equal. This worst case performance of this operation is 00131 // linear in the sizes of the trees. 00132 bool isEqual(const ImutAVLTree& RHS) const { 00133 if (&RHS == this) 00134 return true; 00135 00136 iterator LItr = begin(), LEnd = end(); 00137 iterator RItr = RHS.begin(), REnd = RHS.end(); 00138 00139 while (LItr != LEnd && RItr != REnd) { 00140 if (*LItr == *RItr) { 00141 LItr.SkipSubTree(); 00142 RItr.SkipSubTree(); 00143 continue; 00144 } 00145 00146 if (!LItr->ElementEqual(*RItr)) 00147 return false; 00148 00149 ++LItr; 00150 ++RItr; 00151 } 00152 00153 return LItr == LEnd && RItr == REnd; 00154 } 00155 00156 /// isNotEqual - Compares two trees for structural inequality. Performance 00157 /// is the same is isEqual. 00158 bool isNotEqual(const ImutAVLTree& RHS) const { return !isEqual(RHS); } 00159 00160 /// contains - Returns true if this tree contains a subtree (node) that 00161 /// has an data element that matches the specified key. Complexity 00162 /// is logarithmic in the size of the tree. 00163 bool contains(const key_type_ref K) { return (bool) find(K); } 00164 00165 /// foreach - A member template the accepts invokes operator() on a functor 00166 /// object (specifed by Callback) for every node/subtree in the tree. 00167 /// Nodes are visited using an inorder traversal. 00168 template <typename Callback> 00169 void foreach(Callback& C) { 00170 if (ImutAVLTree* L = getLeft()) L->foreach(C); 00171 00172 C(Value); 00173 00174 if (ImutAVLTree* R = getRight()) R->foreach(C); 00175 } 00176 00177 /// verify - A utility method that checks that the balancing and 00178 /// ordering invariants of the tree are satisifed. It is a recursive 00179 /// method that returns the height of the tree, which is then consumed 00180 /// by the enclosing verify call. External callers should ignore the 00181 /// return value. An invalid tree will cause an assertion to fire in 00182 /// a debug build. 00183 unsigned verify() const { 00184 unsigned HL = getLeft() ? getLeft()->verify() : 0; 00185 unsigned HR = getRight() ? getRight()->verify() : 0; 00186 00187 assert (getHeight() == ( HL > HR ? HL : HR ) + 1 00188 && "Height calculation wrong."); 00189 00190 assert ((HL > HR ? HL-HR : HR-HL) <= 2 00191 && "Balancing invariant violated."); 00192 00193 00194 assert (!getLeft() 00195 || ImutInfo::isLess(ImutInfo::KeyOfValue(getLeft()->getValue()), 00196 ImutInfo::KeyOfValue(getValue())) 00197 && "Value in left child is not less that current value."); 00198 00199 00200 assert (!getRight() 00201 || ImutInfo::isLess(ImutInfo::KeyOfValue(getValue()), 00202 ImutInfo::KeyOfValue(getRight()->getValue())) 00203 && "Current value is not less that value of right child."); 00204 00205 return getHeight(); 00206 } 00207 00208 /// Profile - Profiling for ImutAVLTree. 00209 void Profile(llvm::FoldingSetNodeID& ID) { 00210 ID.AddInteger(ComputeDigest()); 00211 } 00212 00213 //===----------------------------------------------------===// 00214 // Internal Values. 00215 //===----------------------------------------------------===// 00216 00217 private: 00218 uintptr_t Left; 00219 ImutAVLTree* Right; 00220 unsigned Height; 00221 value_type Value; 00222 unsigned Digest; 00223 00224 //===----------------------------------------------------===// 00225 // Internal methods (node manipulation; used by Factory). 00226 //===----------------------------------------------------===// 00227 00228 private: 00229 00230 enum { Mutable = 0x1 }; 00231 00232 /// ImutAVLTree - Internal constructor that is only called by 00233 /// ImutAVLFactory. 00234 ImutAVLTree(ImutAVLTree* l, ImutAVLTree* r, value_type_ref v, unsigned height) 00235 : Left(reinterpret_cast<uintptr_t>(l) | Mutable), 00236 Right(r), Height(height), Value(v), Digest(0) {} 00237 00238 00239 /// isMutable - Returns true if the left and right subtree references 00240 /// (as well as height) can be changed. If this method returns false, 00241 /// the tree is truly immutable. Trees returned from an ImutAVLFactory 00242 /// object should always have this method return true. Further, if this 00243 /// method returns false for an instance of ImutAVLTree, all subtrees 00244 /// will also have this method return false. The converse is not true. 00245 bool isMutable() const { return Left & Mutable; } 00246 00247 /// getSafeLeft - Returns the pointer to the left tree by always masking 00248 /// out the mutable bit. This is used internally by ImutAVLFactory, 00249 /// as no trees returned to the client should have the mutable flag set. 00250 ImutAVLTree* getSafeLeft() const { 00251 return reinterpret_cast<ImutAVLTree*>(Left & ~Mutable); 00252 } 00253 00254 //===----------------------------------------------------===// 00255 // Mutating operations. A tree root can be manipulated as 00256 // long as its reference has not "escaped" from internal 00257 // methods of a factory object (see below). When a tree 00258 // pointer is externally viewable by client code, the 00259 // internal "mutable bit" is cleared to mark the tree 00260 // immutable. Note that a tree that still has its mutable 00261 // bit set may have children (subtrees) that are themselves 00262 // immutable. 00263 //===----------------------------------------------------===// 00264 00265 00266 /// MarkImmutable - Clears the mutable flag for a tree. After this happens, 00267 /// it is an error to call setLeft(), setRight(), and setHeight(). It 00268 /// is also then safe to call getLeft() instead of getSafeLeft(). 00269 void MarkImmutable() { 00270 assert (isMutable() && "Mutable flag already removed."); 00271 Left &= ~Mutable; 00272 } 00273 00274 /// setLeft - Changes the reference of the left subtree. Used internally 00275 /// by ImutAVLFactory. 00276 void setLeft(ImutAVLTree* NewLeft) { 00277 assert (isMutable() && 00278 "Only a mutable tree can have its left subtree changed."); 00279 00280 Left = reinterpret_cast<uintptr_t>(NewLeft) | Mutable; 00281 } 00282 00283 /// setRight - Changes the reference of the right subtree. Used internally 00284 /// by ImutAVLFactory. 00285 void setRight(ImutAVLTree* NewRight) { 00286 assert (isMutable() && 00287 "Only a mutable tree can have its right subtree changed."); 00288 00289 Right = NewRight; 00290 } 00291 00292 /// setHeight - Changes the height of the tree. Used internally by 00293 /// ImutAVLFactory. 00294 void setHeight(unsigned h) { 00295 assert (isMutable() && "Only a mutable tree can have its height changed."); 00296 Height = h; 00297 } 00298 00299 00300 static inline 00301 unsigned ComputeDigest(ImutAVLTree* L, ImutAVLTree* R, value_type_ref V) { 00302 unsigned digest = 0; 00303 00304 if (L) digest += L->ComputeDigest(); 00305 00306 { // Compute digest of stored data. 00307 FoldingSetNodeID ID; 00308 ImutInfo::Profile(ID,V); 00309 digest += ID.ComputeHash(); 00310 } 00311 00312 if (R) digest += R->ComputeDigest(); 00313 00314 return digest; 00315 } 00316 00317 inline unsigned ComputeDigest() { 00318 if (Digest) return Digest; 00319 00320 unsigned X = ComputeDigest(getSafeLeft(), getRight(), getValue()); 00321 if (!isMutable()) Digest = X; 00322 00323 return X; 00324 } 00325 }; 00326 00327 //===----------------------------------------------------------------------===// 00328 // Immutable AVL-Tree Factory class. 00329 //===----------------------------------------------------------------------===// 00330 00331 template <typename ImutInfo > 00332 class ImutAVLFactory { 00333 typedef ImutAVLTree<ImutInfo> TreeTy; 00334 typedef typename TreeTy::value_type_ref value_type_ref; 00335 typedef typename TreeTy::key_type_ref key_type_ref; 00336 00337 typedef FoldingSet<TreeTy> CacheTy; 00338 00339 CacheTy Cache; 00340 uintptr_t Allocator; 00341 00342 bool ownsAllocator() const { 00343 return Allocator & 0x1 ? false : true; 00344 } 00345 00346 BumpPtrAllocator& getAllocator() const { 00347 return *reinterpret_cast<BumpPtrAllocator*>(Allocator & ~0x1); 00348 } 00349 00350 //===--------------------------------------------------===// 00351 // Public interface. 00352 //===--------------------------------------------------===// 00353 00354 public: 00355 ImutAVLFactory() 00356 : Allocator(reinterpret_cast<uintptr_t>(new BumpPtrAllocator())) {} 00357 00358 ImutAVLFactory(BumpPtrAllocator& Alloc) 00359 : Allocator(reinterpret_cast<uintptr_t>(&Alloc) | 0x1) {} 00360 00361 ~ImutAVLFactory() { 00362 if (ownsAllocator()) delete &getAllocator(); 00363 } 00364 00365 TreeTy* Add(TreeTy* T, value_type_ref V) { 00366 T = Add_internal(V,T); 00367 MarkImmutable(T); 00368 return T; 00369 } 00370 00371 TreeTy* Remove(TreeTy* T, key_type_ref V) { 00372 T = Remove_internal(V,T); 00373 MarkImmutable(T); 00374 return T; 00375 } 00376 00377 TreeTy* GetEmptyTree() const { return NULL; } 00378 00379 //===--------------------------------------------------===// 00380 // A bunch of quick helper functions used for reasoning 00381 // about the properties of trees and their children. 00382 // These have succinct names so that the balancing code 00383 // is as terse (and readable) as possible. 00384 //===--------------------------------------------------===// 00385 private: 00386 00387 bool isEmpty(TreeTy* T) const { return !T; } 00388 unsigned Height(TreeTy* T) const { return T ? T->getHeight() : 0; } 00389 TreeTy* Left(TreeTy* T) const { return T->getSafeLeft(); } 00390 TreeTy* Right(TreeTy* T) const { return T->getRight(); } 00391 value_type_ref Value(TreeTy* T) const { return T->Value; } 00392 00393 unsigned IncrementHeight(TreeTy* L, TreeTy* R) const { 00394 unsigned hl = Height(L); 00395 unsigned hr = Height(R); 00396 return ( hl > hr ? hl : hr ) + 1; 00397 } 00398 00399 00400 static bool CompareTreeWithSection(TreeTy* T, 00401 typename TreeTy::iterator& TI, 00402 typename TreeTy::iterator& TE) { 00403 00404 typename TreeTy::iterator I = T->begin(), E = T->end(); 00405 00406 for ( ; I!=E ; ++I, ++TI) 00407 if (TI == TE || !I->ElementEqual(*TI)) 00408 return false; 00409 00410 return true; 00411 } 00412 00413 //===--------------------------------------------------===// 00414 // "CreateNode" is used to generate new tree roots that link 00415 // to other trees. The functon may also simply move links 00416 // in an existing root if that root is still marked mutable. 00417 // This is necessary because otherwise our balancing code 00418 // would leak memory as it would create nodes that are 00419 // then discarded later before the finished tree is 00420 // returned to the caller. 00421 //===--------------------------------------------------===// 00422 00423 TreeTy* CreateNode(TreeTy* L, value_type_ref V, TreeTy* R) { 00424 // Search the FoldingSet bucket for a Tree with the same digest. 00425 FoldingSetNodeID ID; 00426 unsigned digest = TreeTy::ComputeDigest(L, R, V); 00427 ID.AddInteger(digest); 00428 unsigned hash = ID.ComputeHash(); 00429 00430 typename CacheTy::bucket_iterator I = Cache.bucket_begin(hash); 00431 typename CacheTy::bucket_iterator E = Cache.bucket_end(hash); 00432 00433 for (; I != E; ++I) { 00434 TreeTy* T = &*I; 00435 00436 if (T->ComputeDigest() != digest) 00437 continue; 00438 00439 // We found a collision. Perform a comparison of Contents('T') 00440 // with Contents('L')+'V'+Contents('R'). 00441 00442 typename TreeTy::iterator TI = T->begin(), TE = T->end(); 00443 00444 // First compare Contents('L') with the (initial) contents of T. 00445 if (!CompareTreeWithSection(L, TI, TE)) 00446 continue; 00447 00448 // Now compare the new data element. 00449 if (TI == TE || !TI->ElementEqual(V)) 00450 continue; 00451 00452 ++TI; 00453 00454 // Now compare the remainder of 'T' with 'R'. 00455 if (!CompareTreeWithSection(R, TI, TE)) 00456 continue; 00457 00458 if (TI != TE) // Contents('R') did not match suffix of 'T'. 00459 continue; 00460 00461 // Trees did match! Return 'T'. 00462 return T; 00463 } 00464 00465 // No tree with the contents: Contents('L')+'V'+Contents('R'). 00466 // Create it. 00467 00468 // Allocate the new tree node and insert it into the cache. 00469 BumpPtrAllocator& A = getAllocator(); 00470 TreeTy* T = (TreeTy*) A.Allocate<TreeTy>(); 00471 new (T) TreeTy(L,R,V,IncrementHeight(L,R)); 00472 00473 // We do not insert 'T' into the FoldingSet here. This is because 00474 // this tree is still mutable and things may get rebalanced. 00475 // Because our digest is associative and based on the contents of 00476 // the set, this should hopefully not cause any strange bugs. 00477 // 'T' is inserted by 'MarkImmutable'. 00478 00479 return T; 00480 } 00481 00482 TreeTy* CreateNode(TreeTy* L, TreeTy* OldTree, TreeTy* R) { 00483 assert (!isEmpty(OldTree)); 00484 00485 if (OldTree->isMutable()) { 00486 OldTree->setLeft(L); 00487 OldTree->setRight(R); 00488 OldTree->setHeight(IncrementHeight(L,R)); 00489 return OldTree; 00490 } 00491 else return CreateNode(L, Value(OldTree), R); 00492 } 00493 00494 /// Balance - Used by Add_internal and Remove_internal to 00495 /// balance a newly created tree. 00496 TreeTy* Balance(TreeTy* L, value_type_ref V, TreeTy* R) { 00497 00498 unsigned hl = Height(L); 00499 unsigned hr = Height(R); 00500 00501 if (hl > hr + 2) { 00502 assert (!isEmpty(L) && 00503 "Left tree cannot be empty to have a height >= 2."); 00504 00505 TreeTy* LL = Left(L); 00506 TreeTy* LR = Right(L); 00507 00508 if (Height(LL) >= Height(LR)) 00509 return CreateNode(LL, L, CreateNode(LR,V,R)); 00510 00511 assert (!isEmpty(LR) && 00512 "LR cannot be empty because it has a height >= 1."); 00513 00514 TreeTy* LRL = Left(LR); 00515 TreeTy* LRR = Right(LR); 00516 00517 return CreateNode(CreateNode(LL,L,LRL), LR, CreateNode(LRR,V,R)); 00518 } 00519 else if (hr > hl + 2) { 00520 assert (!isEmpty(R) && 00521 "Right tree cannot be empty to have a height >= 2."); 00522 00523 TreeTy* RL = Left(R); 00524 TreeTy* RR = Right(R); 00525 00526 if (Height(RR) >= Height(RL)) 00527 return CreateNode(CreateNode(L,V,RL), R, RR); 00528 00529 assert (!isEmpty(RL) && 00530 "RL cannot be empty because it has a height >= 1."); 00531 00532 TreeTy* RLL = Left(RL); 00533 TreeTy* RLR = Right(RL); 00534 00535 return CreateNode(CreateNode(L,V,RLL), RL, CreateNode(RLR,R,RR)); 00536 } 00537 else 00538 return CreateNode(L,V,R); 00539 } 00540 00541 /// Add_internal - Creates a new tree that includes the specified 00542 /// data and the data from the original tree. If the original tree 00543 /// already contained the data item, the original tree is returned. 00544 TreeTy* Add_internal(value_type_ref V, TreeTy* T) { 00545 if (isEmpty(T)) 00546 return CreateNode(T, V, T); 00547 00548 assert (!T->isMutable()); 00549 00550 key_type_ref K = ImutInfo::KeyOfValue(V); 00551 key_type_ref KCurrent = ImutInfo::KeyOfValue(Value(T)); 00552 00553 if (ImutInfo::isEqual(K,KCurrent)) 00554 return CreateNode(Left(T), V, Right(T)); 00555 else if (ImutInfo::isLess(K,KCurrent)) 00556 return Balance(Add_internal(V,Left(T)), Value(T), Right(T)); 00557 else 00558 return Balance(Left(T), Value(T), Add_internal(V,Right(T))); 00559 } 00560 00561 /// Remove_internal - Creates a new tree that includes all the data 00562 /// from the original tree except the specified data. If the 00563 /// specified data did not exist in the original tree, the original 00564 /// tree is returned. 00565 TreeTy* Remove_internal(key_type_ref K, TreeTy* T) { 00566 if (isEmpty(T)) 00567 return T; 00568 00569 assert (!T->isMutable()); 00570 00571 key_type_ref KCurrent = ImutInfo::KeyOfValue(Value(T)); 00572 00573 if (ImutInfo::isEqual(K,KCurrent)) 00574 return CombineLeftRightTrees(Left(T),Right(T)); 00575 else if (ImutInfo::isLess(K,KCurrent)) 00576 return Balance(Remove_internal(K,Left(T)), Value(T), Right(T)); 00577 else 00578 return Balance(Left(T), Value(T), Remove_internal(K,Right(T))); 00579 } 00580 00581 TreeTy* CombineLeftRightTrees(TreeTy* L, TreeTy* R) { 00582 if (isEmpty(L)) return R; 00583 if (isEmpty(R)) return L; 00584 00585 TreeTy* OldNode; 00586 TreeTy* NewRight = RemoveMinBinding(R,OldNode); 00587 return Balance(L,Value(OldNode),NewRight); 00588 } 00589 00590 TreeTy* RemoveMinBinding(TreeTy* T, TreeTy*& NodeRemoved) { 00591 assert (!isEmpty(T)); 00592 00593 if (isEmpty(Left(T))) { 00594 NodeRemoved = T; 00595 return Right(T); 00596 } 00597 00598 return Balance(RemoveMinBinding(Left(T),NodeRemoved),Value(T),Right(T)); 00599 } 00600 00601 /// MarkImmutable - Clears the mutable bits of a root and all of its 00602 /// descendants. 00603 void MarkImmutable(TreeTy* T) { 00604 if (!T || !T->isMutable()) 00605 return; 00606 00607 T->MarkImmutable(); 00608 MarkImmutable(Left(T)); 00609 MarkImmutable(Right(T)); 00610 00611 // Now that the node is immutable it can safely be inserted 00612 // into the node cache. 00613 llvm::FoldingSetNodeID ID; 00614 ID.AddInteger(T->ComputeDigest()); 00615 Cache.InsertNode(T, (void*) &*Cache.bucket_end(ID.ComputeHash())); 00616 } 00617 }; 00618 00619 00620 //===----------------------------------------------------------------------===// 00621 // Immutable AVL-Tree Iterators. 00622 //===----------------------------------------------------------------------===// 00623 00624 template <typename ImutInfo> 00625 class ImutAVLTreeGenericIterator { 00626 SmallVector<uintptr_t,20> stack; 00627 public: 00628 enum VisitFlag { VisitedNone=0x0, VisitedLeft=0x1, VisitedRight=0x3, 00629 Flags=0x3 }; 00630 00631 typedef ImutAVLTree<ImutInfo> TreeTy; 00632 typedef ImutAVLTreeGenericIterator<ImutInfo> _Self; 00633 00634 inline ImutAVLTreeGenericIterator() {} 00635 inline ImutAVLTreeGenericIterator(const TreeTy* Root) { 00636 if (Root) stack.push_back(reinterpret_cast<uintptr_t>(Root)); 00637 } 00638 00639 TreeTy* operator*() const { 00640 assert (!stack.empty()); 00641 return reinterpret_cast<TreeTy*>(stack.back() & ~Flags); 00642 } 00643 00644 uintptr_t getVisitState() { 00645 assert (!stack.empty()); 00646 return stack.back() & Flags; 00647 } 00648 00649 00650 bool AtEnd() const { return stack.empty(); } 00651 00652 bool AtBeginning() const { 00653 return stack.size() == 1 && getVisitState() == VisitedNone; 00654 } 00655 00656 void SkipToParent() { 00657 assert (!stack.empty()); 00658 stack.pop_back(); 00659 00660 if (stack.empty()) 00661 return; 00662 00663 switch (getVisitState()) { 00664 case VisitedNone: 00665 stack.back() |= VisitedLeft; 00666 break; 00667 case VisitedLeft: 00668 stack.back() |= VisitedRight; 00669 break; 00670 default: 00671 assert (false && "Unreachable."); 00672 } 00673 } 00674 00675 inline bool operator==(const _Self& x) const { 00676 if (stack.size() != x.stack.size()) 00677 return false; 00678 00679 for (unsigned i = 0 ; i < stack.size(); i++) 00680 if (stack[i] != x.stack[i]) 00681 return false; 00682 00683 return true; 00684 } 00685 00686 inline bool operator!=(const _Self& x) const { return !operator==(x); } 00687 00688 _Self& operator++() { 00689 assert (!stack.empty()); 00690 00691 TreeTy* Current = reinterpret_cast<TreeTy*>(stack.back() & ~Flags); 00692 assert (Current); 00693 00694 switch (getVisitState()) { 00695 case VisitedNone: 00696 if (TreeTy* L = Current->getSafeLeft()) 00697 stack.push_back(reinterpret_cast<uintptr_t>(L)); 00698 else 00699 stack.back() |= VisitedLeft; 00700 00701 break; 00702 00703 case VisitedLeft: 00704 if (TreeTy* R = Current->getRight()) 00705 stack.push_back(reinterpret_cast<uintptr_t>(R)); 00706 else 00707 stack.back() |= VisitedRight; 00708 00709 break; 00710 00711 case VisitedRight: 00712 SkipToParent(); 00713 break; 00714 00715 default: 00716 assert (false && "Unreachable."); 00717 } 00718 00719 return *this; 00720 } 00721 00722 _Self& operator--() { 00723 assert (!stack.empty()); 00724 00725 TreeTy* Current = reinterpret_cast<TreeTy*>(stack.back() & ~Flags); 00726 assert (Current); 00727 00728 switch (getVisitState()) { 00729 case VisitedNone: 00730 stack.pop_back(); 00731 break; 00732 00733 case VisitedLeft: 00734 stack.back() &= ~Flags; // Set state to "VisitedNone." 00735 00736 if (TreeTy* L = Current->getLeft()) 00737 stack.push_back(reinterpret_cast<uintptr_t>(L) | VisitedRight); 00738 00739 break; 00740 00741 case VisitedRight: 00742 stack.back() &= ~Flags; 00743 stack.back() |= VisitedLeft; 00744 00745 if (TreeTy* R = Current->getRight()) 00746 stack.push_back(reinterpret_cast<uintptr_t>(R) | VisitedRight); 00747 00748 break; 00749 00750 default: 00751 assert (false && "Unreachable."); 00752 } 00753 00754 return *this; 00755 } 00756 }; 00757 00758 template <typename ImutInfo> 00759 class ImutAVLTreeInOrderIterator { 00760 typedef ImutAVLTreeGenericIterator<ImutInfo> InternalIteratorTy; 00761 InternalIteratorTy InternalItr; 00762 00763 public: 00764 typedef ImutAVLTree<ImutInfo> TreeTy; 00765 typedef ImutAVLTreeInOrderIterator<ImutInfo> _Self; 00766 00767 ImutAVLTreeInOrderIterator(const TreeTy* Root) : InternalItr(Root) { 00768 if (Root) operator++(); // Advance to first element. 00769 } 00770 00771 ImutAVLTreeInOrderIterator() : InternalItr() {} 00772 00773 inline bool operator==(const _Self& x) const { 00774 return InternalItr == x.InternalItr; 00775 } 00776 00777 inline bool operator!=(const _Self& x) const { return !operator==(x); } 00778 00779 inline TreeTy* operator*() const { return *InternalItr; } 00780 inline TreeTy* operator->() const { return *InternalItr; } 00781 00782 inline _Self& operator++() { 00783 do ++InternalItr; 00784 while (!InternalItr.AtEnd() && 00785 InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft); 00786 00787 return *this; 00788 } 00789 00790 inline _Self& operator--() { 00791 do --InternalItr; 00792 while (!InternalItr.AtBeginning() && 00793 InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft); 00794 00795 return *this; 00796 } 00797 00798 inline void SkipSubTree() { 00799 InternalItr.SkipToParent(); 00800 00801 while (!InternalItr.AtEnd() && 00802 InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft) 00803 ++InternalItr; 00804 } 00805 }; 00806 00807 //===----------------------------------------------------------------------===// 00808 // Trait classes for Profile information. 00809 //===----------------------------------------------------------------------===// 00810 00811 /// Generic profile template. The default behavior is to invoke the 00812 /// profile method of an object. Specializations for primitive integers 00813 /// and generic handling of pointers is done below. 00814 template <typename T> 00815 struct ImutProfileInfo { 00816 typedef const T value_type; 00817 typedef const T& value_type_ref; 00818 00819 static inline void Profile(FoldingSetNodeID& ID, value_type_ref X) { 00820 FoldingSetTrait<T>::Profile(X,ID); 00821 } 00822 }; 00823 00824 /// Profile traits for integers. 00825 template <typename T> 00826 struct ImutProfileInteger { 00827 typedef const T value_type; 00828 typedef const T& value_type_ref; 00829 00830 static inline void Profile(FoldingSetNodeID& ID, value_type_ref X) { 00831 ID.AddInteger(X); 00832 } 00833 }; 00834 00835 #define PROFILE_INTEGER_INFO(X)\ 00836 template<> struct ImutProfileInfo<X> : ImutProfileInteger<X> {}; 00837 00838 PROFILE_INTEGER_INFO(char) 00839 PROFILE_INTEGER_INFO(unsigned char) 00840 PROFILE_INTEGER_INFO(short) 00841 PROFILE_INTEGER_INFO(unsigned short) 00842 PROFILE_INTEGER_INFO(unsigned) 00843 PROFILE_INTEGER_INFO(signed) 00844 PROFILE_INTEGER_INFO(long) 00845 PROFILE_INTEGER_INFO(unsigned long) 00846 PROFILE_INTEGER_INFO(long long) 00847 PROFILE_INTEGER_INFO(unsigned long long) 00848 00849 #undef PROFILE_INTEGER_INFO 00850 00851 /// Generic profile trait for pointer types. We treat pointers as 00852 /// references to unique objects. 00853 template <typename T> 00854 struct ImutProfileInfo<T*> { 00855 typedef const T* value_type; 00856 typedef value_type value_type_ref; 00857 00858 static inline void Profile(FoldingSetNodeID &ID, value_type_ref X) { 00859 ID.AddPointer(X); 00860 } 00861 }; 00862 00863 //===----------------------------------------------------------------------===// 00864 // Trait classes that contain element comparison operators and type 00865 // definitions used by ImutAVLTree, ImmutableSet, and ImmutableMap. These 00866 // inherit from the profile traits (ImutProfileInfo) to include operations 00867 // for element profiling. 00868 //===----------------------------------------------------------------------===// 00869 00870 00871 /// ImutContainerInfo - Generic definition of comparison operations for 00872 /// elements of immutable containers that defaults to using 00873 /// std::equal_to<> and std::less<> to perform comparison of elements. 00874 template <typename T> 00875 struct ImutContainerInfo : public ImutProfileInfo<T> { 00876 typedef typename ImutProfileInfo<T>::value_type value_type; 00877 typedef typename ImutProfileInfo<T>::value_type_ref value_type_ref; 00878 typedef value_type key_type; 00879 typedef value_type_ref key_type_ref; 00880 typedef bool data_type; 00881 typedef bool data_type_ref; 00882 00883 static inline key_type_ref KeyOfValue(value_type_ref D) { return D; } 00884 static inline data_type_ref DataOfValue(value_type_ref) { return true; } 00885 00886 static inline bool isEqual(key_type_ref LHS, key_type_ref RHS) { 00887 return std::equal_to<key_type>()(LHS,RHS); 00888 } 00889 00890 static inline bool isLess(key_type_ref LHS, key_type_ref RHS) { 00891 return std::less<key_type>()(LHS,RHS); 00892 } 00893 00894 static inline bool isDataEqual(data_type_ref,data_type_ref) { return true; } 00895 }; 00896 00897 /// ImutContainerInfo - Specialization for pointer values to treat pointers 00898 /// as references to unique objects. Pointers are thus compared by 00899 /// their addresses. 00900 template <typename T> 00901 struct ImutContainerInfo<T*> : public ImutProfileInfo<T*> { 00902 typedef typename ImutProfileInfo<T*>::value_type value_type; 00903 typedef typename ImutProfileInfo<T*>::value_type_ref value_type_ref; 00904 typedef value_type key_type; 00905 typedef value_type_ref key_type_ref; 00906 typedef bool data_type; 00907 typedef bool data_type_ref; 00908 00909 static inline key_type_ref KeyOfValue(value_type_ref D) { return D; } 00910 static inline data_type_ref DataOfValue(value_type_ref) { return true; } 00911 00912 static inline bool isEqual(key_type_ref LHS, key_type_ref RHS) { 00913 return LHS == RHS; 00914 } 00915 00916 static inline bool isLess(key_type_ref LHS, key_type_ref RHS) { 00917 return LHS < RHS; 00918 } 00919 00920 static inline bool isDataEqual(data_type_ref,data_type_ref) { return true; } 00921 }; 00922 00923 //===----------------------------------------------------------------------===// 00924 // Immutable Set 00925 //===----------------------------------------------------------------------===// 00926 00927 template <typename ValT, typename ValInfo = ImutContainerInfo<ValT> > 00928 class ImmutableSet { 00929 public: 00930 typedef typename ValInfo::value_type value_type; 00931 typedef typename ValInfo::value_type_ref value_type_ref; 00932 typedef ImutAVLTree<ValInfo> TreeTy; 00933 00934 private: 00935 TreeTy* Root; 00936 00937 public: 00938 /// Constructs a set from a pointer to a tree root. In general one 00939 /// should use a Factory object to create sets instead of directly 00940 /// invoking the constructor, but there are cases where make this 00941 /// constructor public is useful. 00942 explicit ImmutableSet(TreeTy* R) : Root(R) {} 00943 00944 class Factory { 00945 typename TreeTy::Factory F; 00946 00947 public: 00948 Factory() {} 00949 00950 Factory(BumpPtrAllocator& Alloc) 00951 : F(Alloc) {} 00952 00953 /// GetEmptySet - Returns an immutable set that contains no elements. 00954 ImmutableSet GetEmptySet() { return ImmutableSet(F.GetEmptyTree()); } 00955 00956 /// Add - Creates a new immutable set that contains all of the values 00957 /// of the original set with the addition of the specified value. If 00958 /// the original set already included the value, then the original set is 00959 /// returned and no memory is allocated. The time and space complexity 00960 /// of this operation is logarithmic in the size of the original set. 00961 /// The memory allocated to represent the set is released when the 00962 /// factory object that created the set is destroyed. 00963 ImmutableSet Add(ImmutableSet Old, value_type_ref V) { 00964 return ImmutableSet(F.Add(Old.Root,V)); 00965 } 00966 00967 /// Remove - Creates a new immutable set that contains all of the values 00968 /// of the original set with the exception of the specified value. If 00969 /// the original set did not contain the value, the original set is 00970 /// returned and no memory is allocated. The time and space complexity 00971 /// of this operation is logarithmic in the size of the original set. 00972 /// The memory allocated to represent the set is released when the 00973 /// factory object that created the set is destroyed. 00974 ImmutableSet Remove(ImmutableSet Old, value_type_ref V) { 00975 return ImmutableSet(F.Remove(Old.Root,V)); 00976 } 00977 00978 BumpPtrAllocator& getAllocator() { return F.getAllocator(); } 00979 00980 private: 00981 Factory(const Factory& RHS) {}; 00982 void operator=(const Factory&