Removed "height" of an AVL tree node from its Profile. This is
[oota-llvm.git] / include / llvm / ADT / ImmutableSet.h
1 //===--- ImmutableSet.h - Immutable (functional) set interface --*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by Ted Kremenek and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines the ImutAVLTree and ImmutableSet classes.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_ADT_IMSET_H
15 #define LLVM_ADT_IMSET_H
16
17 #include "llvm/Support/Allocator.h"
18 #include "llvm/ADT/FoldingSet.h"
19 #include <cassert>
20
21 namespace llvm {
22   
23 //===----------------------------------------------------------------------===//    
24 // Immutable AVL-Tree Definition.
25 //===----------------------------------------------------------------------===//
26
27 template <typename ImutInfo> class ImutAVLFactory;
28
29 template <typename ImutInfo> class ImutAVLTreeInOrderIterator;
30   
31 template <typename ImutInfo >
32 class ImutAVLTree : public FoldingSetNode {
33 public:
34   typedef typename ImutInfo::key_type_ref   key_type_ref;
35   typedef typename ImutInfo::value_type     value_type;
36   typedef typename ImutInfo::value_type_ref value_type_ref;
37
38   typedef ImutAVLFactory<ImutInfo>          Factory;
39   friend class ImutAVLFactory<ImutInfo>;
40   
41   typedef ImutAVLTreeInOrderIterator<ImutInfo>  iterator;
42   
43   //===----------------------------------------------------===//  
44   // Public Interface.
45   //===----------------------------------------------------===//  
46   
47   /// getLeft - Returns a pointer to the left subtree.  This value
48   ///  is NULL if there is no left subtree.
49   ImutAVLTree* getLeft() const { 
50     assert (!isMutable() && "Node is incorrectly marked mutable.");
51     
52     return reinterpret_cast<ImutAVLTree*>(Left);
53   }
54   
55   /// getRight - Returns a pointer to the right subtree.  This value is
56   ///  NULL if there is no right subtree.
57   ImutAVLTree* getRight() const { return Right; }  
58   
59   
60   /// getHeight - Returns the height of the tree.  A tree with no subtrees
61   ///  has a height of 1.
62   unsigned getHeight() const { return Height; }  
63   
64   /// getValue - Returns the data value associated with the tree node.
65   const value_type& getValue() const { return Value; }
66   
67   /// find - Finds the subtree associated with the specified key value.
68   ///  This method returns NULL if no matching subtree is found.
69   ImutAVLTree* find(key_type_ref K) {
70     ImutAVLTree *T = this;
71     
72     while (T) {
73       key_type_ref CurrentKey = ImutInfo::KeyOfValue(T->getValue());
74       
75       if (ImutInfo::isEqual(K,CurrentKey))
76         return T;
77       else if (ImutInfo::isLess(K,CurrentKey))
78         T = T->getLeft();
79       else
80         T = T->getRight();
81     }
82     
83     return NULL;
84   }
85   
86   /// size - Returns the number of nodes in the tree, which includes
87   ///  both leaves and non-leaf nodes.
88   unsigned size() const {
89     unsigned n = 1;
90     
91     if (const ImutAVLTree* L = getLeft())  n += L->size();
92     if (const ImutAVLTree* R = getRight()) n += R->size();
93     
94     return n;
95   }
96   
97   /// begin - Returns an iterator that iterates over the nodes of the tree
98   ///  in an inorder traversal.  The returned iterator thus refers to the
99   ///  the tree node with the minimum data element.
100   iterator begin() const { return iterator(this); }
101   
102   /// end - Returns an iterator for the tree that denotes the end of an
103   ///  inorder traversal.
104   iterator end() const { return iterator(); }
105   
106   /// isEqual - Compares two trees for structural equality and returns true
107   ///   if they are equal.  This worst case performance of this operation is
108   //    linear in the sizes of the trees.
109   bool isEqual(const ImutAVLTree& RHS) const {
110     if (&RHS == this)
111       return true;
112     
113     iterator LItr = begin(), LEnd = end();
114     iterator RItr = RHS.begin(), REnd = RHS.end();
115     
116     while (LItr != LEnd && RItr != REnd) {
117       if (*LItr == *RItr) {
118         LItr.SkipSubTree();
119         RItr.SkipSubTree();
120         continue;
121       }
122       
123       // FIXME: need to compare data values, not key values, but our
124       // traits don't support this yet.
125       if (!ImutInfo::isEqual(ImutInfo::KeyOfValue(LItr->getValue()),
126                              ImutInfo::KeyOfValue(RItr->getValue())))
127         return false;
128       
129       ++LItr;
130       ++RItr;
131     }
132     
133     return LItr == LEnd && RItr == REnd;
134   }
135
136   /// isNotEqual - Compares two trees for structural inequality.  Performance
137   ///  is the same is isEqual.
138   bool isNotEqual(const ImutAVLTree& RHS) const { return !isEqual(RHS); }
139   
140   /// contains - Returns true if this tree contains a subtree (node) that
141   ///  has an data element that matches the specified key.  Complexity
142   ///  is logarithmic in the size of the tree.
143   bool contains(const key_type_ref K) { return (bool) find(K); }
144   
145   /// foreach - A member template the accepts invokes operator() on a functor
146   ///  object (specifed by Callback) for every node/subtree in the tree.
147   ///  Nodes are visited using an inorder traversal.
148   template <typename Callback>
149   void foreach(Callback& C) {
150     if (ImutAVLTree* L = getLeft()) L->foreach(C);
151     
152     C(Value);    
153     
154     if (ImutAVLTree* R = getRight()) R->foreach(C);
155   }
156   
157   /// verify - A utility method that checks that the balancing and
158   ///  ordering invariants of the tree are satisifed.  It is a recursive
159   ///  method that returns the height of the tree, which is then consumed
160   ///  by the enclosing verify call.  External callers should ignore the
161   ///  return value.  An invalid tree will cause an assertion to fire in
162   ///  a debug build.
163   unsigned verify() const {
164     unsigned HL = getLeft() ? getLeft()->verify() : 0;
165     unsigned HR = getRight() ? getRight()->verify() : 0;
166     
167     assert (getHeight() == ( HL > HR ? HL : HR ) + 1 
168             && "Height calculation wrong.");
169     
170     assert ((HL > HR ? HL-HR : HR-HL) <= 2
171             && "Balancing invariant violated.");
172     
173     
174     assert (!getLeft()
175             || ImutInfo::isLess(ImutInfo::KeyOfValue(getLeft()->getValue()),
176                                 ImutInfo::KeyOfValue(getValue()))
177             && "Value in left child is not less that current value.");
178     
179     
180     assert (!getRight()
181             || ImutInfo::isLess(ImutInfo::KeyOfValue(getValue()),
182                                 ImutInfo::KeyOfValue(getRight()->getValue()))
183             && "Current value is not less that value of right child.");
184     
185     return getHeight();
186   }  
187   
188   //===----------------------------------------------------===//  
189   // Internal Values.
190   //===----------------------------------------------------===//
191   
192 private:
193   uintptr_t        Left;
194   ImutAVLTree*     Right;
195   unsigned         Height;
196   value_type       Value;
197   
198   //===----------------------------------------------------===//  
199   // Profiling or FoldingSet.
200   //===----------------------------------------------------===//
201   
202   static inline
203   void Profile(FoldingSetNodeID& ID, ImutAVLTree* L, ImutAVLTree* R,
204                value_type_ref V) {    
205     ID.AddPointer(L);
206     ID.AddPointer(R);
207     ImutInfo::Profile(ID,V);
208   }
209   
210 public:
211   
212   void Profile(FoldingSetNodeID& ID) {
213     Profile(ID,getSafeLeft(),getRight(),getValue());    
214   }
215   
216   //===----------------------------------------------------===//    
217   // Internal methods (node manipulation; used by Factory).
218   //===----------------------------------------------------===//
219   
220 private:
221   
222   ImutAVLTree(ImutAVLTree* l, ImutAVLTree* r, value_type_ref v, unsigned height)
223   : Left(reinterpret_cast<uintptr_t>(l) | 0x1),
224   Right(r), Height(height), Value(v) {}
225   
226   bool isMutable() const { return Left & 0x1; }
227   
228   ImutAVLTree* getSafeLeft() const { 
229     return reinterpret_cast<ImutAVLTree*>(Left & ~0x1);
230   }
231   
232   // Mutating operations.  A tree root can be manipulated as long as
233   // its reference has not "escaped" from internal methods of a
234   // factory object (see below).  When a tree pointer is externally
235   // viewable by client code, the internal "mutable bit" is cleared
236   // to mark the tree immutable.  Note that a tree that still has
237   // its mutable bit set may have children (subtrees) that are themselves
238   // immutable.
239   
240   void RemoveMutableFlag() {
241     assert (Left & 0x1 && "Mutable flag already removed.");
242     Left &= ~0x1;
243   }
244   
245   void setLeft(ImutAVLTree* NewLeft) {
246     assert (isMutable());
247     Left = reinterpret_cast<uintptr_t>(NewLeft) | 0x1;
248   }
249   
250   void setRight(ImutAVLTree* NewRight) {
251     assert (isMutable());
252     Right = NewRight;
253   }
254   
255   void setHeight(unsigned h) {
256     assert (isMutable());
257     Height = h;
258   }
259 };
260
261 //===----------------------------------------------------------------------===//    
262 // Immutable AVL-Tree Factory class.
263 //===----------------------------------------------------------------------===//
264
265 template <typename ImutInfo >  
266 class ImutAVLFactory {
267   typedef ImutAVLTree<ImutInfo> TreeTy;
268   typedef typename TreeTy::value_type_ref value_type_ref;
269   typedef typename TreeTy::key_type_ref   key_type_ref;
270   
271   typedef FoldingSet<TreeTy> CacheTy;
272   
273   CacheTy Cache;  
274   BumpPtrAllocator Allocator;    
275   
276   //===--------------------------------------------------===//    
277   // Public interface.
278   //===--------------------------------------------------===//
279   
280 public:
281   ImutAVLFactory() {}
282   
283   TreeTy* Add(TreeTy* T, value_type_ref V) {
284     T = Add_internal(V,T);
285     MarkImmutable(T);
286     return T;
287   }
288   
289   TreeTy* Remove(TreeTy* T, key_type_ref V) {
290     T = Remove_internal(V,T);
291     MarkImmutable(T);
292     return T;
293   }
294   
295   TreeTy* GetEmptyTree() const { return NULL; }
296   
297   //===--------------------------------------------------===//    
298   // A bunch of quick helper functions used for reasoning
299   // about the properties of trees and their children.
300   // These have succinct names so that the balancing code
301   // is as terse (and readable) as possible.
302   //===--------------------------------------------------===//
303 private:
304   
305   bool isEmpty(TreeTy* T) const {
306     return !T;
307   }
308   
309   unsigned Height(TreeTy* T) const {
310     return T ? T->getHeight() : 0;
311   }
312   
313   TreeTy* Left(TreeTy* T) const {
314     assert (T);
315     return T->getSafeLeft();
316   }
317   
318   TreeTy* Right(TreeTy* T) const {
319     assert (T);
320     return T->getRight();
321   }
322   
323   value_type_ref Value(TreeTy* T) const {
324     assert (T);
325     return T->Value;
326   }
327   
328   unsigned IncrementHeight(TreeTy* L, TreeTy* R) const {
329     unsigned hl = Height(L);
330     unsigned hr = Height(R);
331     return ( hl > hr ? hl : hr ) + 1;
332   }
333   
334   //===--------------------------------------------------===//    
335   // "CreateNode" is used to generate new tree roots that link
336   // to other trees.  The functon may also simply move links
337   // in an existing root if that root is still marked mutable.
338   // This is necessary because otherwise our balancing code
339   // would leak memory as it would create nodes that are
340   // then discarded later before the finished tree is
341   // returned to the caller.
342   //===--------------------------------------------------===//
343   
344   TreeTy* CreateNode(TreeTy* L, value_type_ref V, TreeTy* R) {
345     FoldingSetNodeID ID;      
346     TreeTy::Profile(ID,L,R,V);      
347     void* InsertPos;
348     
349     if (TreeTy* T = Cache.FindNodeOrInsertPos(ID,InsertPos))
350       return T;
351     
352     assert (InsertPos != NULL);
353     
354     // FIXME: more intelligent calculation of alignment.
355     TreeTy* T = (TreeTy*) Allocator.Allocate(sizeof(*T),16);
356     new (T) TreeTy(L,R,V,IncrementHeight(L,R));
357     
358     Cache.InsertNode(T,InsertPos);
359     return T;      
360   }
361   
362   TreeTy* CreateNode(TreeTy* L, TreeTy* OldTree, TreeTy* R) {      
363     assert (!isEmpty(OldTree));
364     
365     if (OldTree->isMutable()) {
366       OldTree->setLeft(L);
367       OldTree->setRight(R);
368       OldTree->setHeight(IncrementHeight(L,R));
369       return OldTree;
370     }
371     else return CreateNode(L, Value(OldTree), R);
372   }
373   
374   /// Balance - Used by Add_internal and Remove_internal to
375   ///  balance a newly created tree.
376   TreeTy* Balance(TreeTy* L, value_type_ref V, TreeTy* R) {
377     
378     unsigned hl = Height(L);
379     unsigned hr = Height(R);
380     
381     if (hl > hr + 2) {
382       assert (!isEmpty(L) &&
383               "Left tree cannot be empty to have a height >= 2.");
384       
385       TreeTy* LL = Left(L);
386       TreeTy* LR = Right(L);
387       
388       if (Height(LL) >= Height(LR))
389         return CreateNode(LL, L, CreateNode(LR,V,R));
390       
391       assert (!isEmpty(LR) &&
392               "LR cannot be empty because it has a height >= 1.");
393       
394       TreeTy* LRL = Left(LR);
395       TreeTy* LRR = Right(LR);
396       
397       return CreateNode(CreateNode(LL,L,LRL), LR, CreateNode(LRR,V,R));                              
398     }
399     else if (hr > hl + 2) {
400       assert (!isEmpty(R) &&
401               "Right tree cannot be empty to have a height >= 2.");
402       
403       TreeTy* RL = Left(R);
404       TreeTy* RR = Right(R);
405       
406       if (Height(RR) >= Height(RL))
407         return CreateNode(CreateNode(L,V,RL), R, RR);
408       
409       assert (!isEmpty(RL) &&
410               "RL cannot be empty because it has a height >= 1.");
411       
412       TreeTy* RLL = Left(RL);
413       TreeTy* RLR = Right(RL);
414       
415       return CreateNode(CreateNode(L,V,RLL), RL, CreateNode(RLR,R,RR));
416     }
417     else
418       return CreateNode(L,V,R);
419   }
420   
421   /// Add_internal - Creates a new tree that includes the specified
422   ///  data and the data from the original tree.  If the original tree
423   ///  already contained the data item, the original tree is returned.
424   TreeTy* Add_internal(value_type_ref V, TreeTy* T) {
425     if (isEmpty(T))
426       return CreateNode(T, V, T);
427     
428     assert (!T->isMutable());
429     
430     key_type_ref K = ImutInfo::KeyOfValue(V);
431     key_type_ref KCurrent = ImutInfo::KeyOfValue(Value(T));
432     
433     if (ImutInfo::isEqual(K,KCurrent))
434       return CreateNode(Left(T), V, Right(T));
435     else if (ImutInfo::isLess(K,KCurrent))
436       return Balance(Add_internal(V,Left(T)), Value(T), Right(T));
437     else
438       return Balance(Left(T), Value(T), Add_internal(V,Right(T)));
439   }
440   
441   /// Remove_interal - Creates a new tree that includes all the data
442   ///  from the original tree except the specified data.  If the
443   ///  specified data did not exist in the original tree, the original
444   ///  tree is returned.
445   TreeTy* Remove_internal(key_type_ref K, TreeTy* T) {
446     if (isEmpty(T))
447       return T;
448     
449     assert (!T->isMutable());
450     
451     key_type_ref KCurrent = ImutInfo::KeyOfValue(Value(T));
452     
453     if (ImutInfo::isEqual(K,KCurrent))
454       return CombineLeftRightTrees(Left(T),Right(T));
455     else if (ImutInfo::isLess(K,KCurrent))
456       return Balance(Remove_internal(K,Left(T)), Value(T), Right(T));
457     else
458       return Balance(Left(T), Value(T), Remove_internal(K,Right(T)));
459   }
460   
461   TreeTy* CombineLeftRightTrees(TreeTy* L, TreeTy* R) {
462     if (isEmpty(L)) return R;      
463     if (isEmpty(R)) return L;
464     
465     TreeTy* OldNode;          
466     TreeTy* NewRight = RemoveMinBinding(R,OldNode);
467     return Balance(L,Value(OldNode),NewRight);
468   }
469   
470   TreeTy* RemoveMinBinding(TreeTy* T, TreeTy*& NodeRemoved) {
471     assert (!isEmpty(T));
472     
473     if (isEmpty(Left(T))) {
474       NodeRemoved = T;
475       return Right(T);
476     }
477     
478     return Balance(RemoveMinBinding(Left(T),NodeRemoved),Value(T),Right(T));
479   }    
480   
481   /// MarkImmutable - Clears the mutable bits of a root and all of its
482   ///  descendants.
483   void MarkImmutable(TreeTy* T) {
484     if (!T || !T->isMutable())
485       return;
486     
487     T->RemoveMutableFlag();
488     MarkImmutable(Left(T));
489     MarkImmutable(Right(T));
490   }
491 };
492   
493   
494 //===----------------------------------------------------------------------===//    
495 // Immutable AVL-Tree Iterators.
496 //===----------------------------------------------------------------------===//  
497
498 template <typename ImutInfo>
499 class ImutAVLTreeGenericIterator {
500   SmallVector<uintptr_t,20> stack;
501 public:
502   enum VisitFlag { VisitedNone=0x0, VisitedLeft=0x1, VisitedRight=0x3, 
503                    Flags=0x3 };
504   
505   typedef ImutAVLTree<ImutInfo> TreeTy;      
506   typedef ImutAVLTreeGenericIterator<ImutInfo> _Self;
507
508   inline ImutAVLTreeGenericIterator() {}
509   inline ImutAVLTreeGenericIterator(const TreeTy* Root) {
510     if (Root) stack.push_back(reinterpret_cast<uintptr_t>(Root));
511   }  
512   
513   TreeTy* operator*() const {
514     assert (!stack.empty());    
515     return reinterpret_cast<TreeTy*>(stack.back() & ~Flags);
516   }
517   
518   uintptr_t getVisitState() {
519     assert (!stack.empty());
520     return stack.back() & Flags;
521   }
522   
523   
524   bool AtEnd() const { return stack.empty(); }
525
526   bool AtBeginning() const { 
527     return stack.size() == 1 && getVisitState() == VisitedNone;
528   }
529   
530   void SkipToParent() {
531     assert (!stack.empty());
532     stack.pop_back();
533     
534     if (stack.empty())
535       return;
536     
537     switch (getVisitState()) {
538       case VisitedNone:
539         stack.back() |= VisitedLeft;
540         break;
541       case VisitedLeft:
542         stack.back() |= VisitedRight;
543         break;
544       default:
545         assert (false && "Unreachable.");            
546     }
547   }
548   
549   inline bool operator==(const _Self& x) const {
550     if (stack.size() != x.stack.size())
551       return false;
552     
553     for (unsigned i = 0 ; i < stack.size(); i++)
554       if (stack[i] != x.stack[i])
555         return false;
556     
557     return true;
558   }
559   
560   inline bool operator!=(const _Self& x) const { return !operator==(x); }  
561   
562   _Self& operator++() {
563     assert (!stack.empty());
564     
565     TreeTy* Current = reinterpret_cast<TreeTy*>(stack.back() & ~Flags);
566     assert (Current);
567     
568     switch (getVisitState()) {
569       case VisitedNone:
570         if (TreeTy* L = Current->getLeft())
571           stack.push_back(reinterpret_cast<uintptr_t>(L));
572         else
573           stack.back() |= VisitedLeft;
574         
575         break;
576         
577       case VisitedLeft:
578         if (TreeTy* R = Current->getRight())
579           stack.push_back(reinterpret_cast<uintptr_t>(R));
580         else
581           stack.back() |= VisitedRight;
582         
583         break;
584         
585       case VisitedRight:
586         SkipToParent();        
587         break;
588         
589       default:
590         assert (false && "Unreachable.");
591     }
592     
593     return *this;
594   }
595   
596   _Self& operator--() {
597     assert (!stack.empty());
598     
599     TreeTy* Current = reinterpret_cast<TreeTy*>(stack.back() & ~Flags);
600     assert (Current);
601     
602     switch (getVisitState()) {
603       case VisitedNone:
604         stack.pop_back();
605         break;
606         
607       case VisitedLeft:                
608         stack.back() &= ~Flags; // Set state to "VisitedNone."
609         
610         if (TreeTy* L = Current->getLeft())
611           stack.push_back(reinterpret_cast<uintptr_t>(L) | VisitedRight);
612           
613         break;
614         
615       case VisitedRight:        
616         stack.back() &= ~Flags;
617         stack.back() |= VisitedLeft;
618         
619         if (TreeTy* R = Current->getRight())
620           stack.push_back(reinterpret_cast<uintptr_t>(R) | VisitedRight);
621           
622         break;
623         
624       default:
625         assert (false && "Unreachable.");
626     }
627     
628     return *this;
629   }
630 };
631   
632 template <typename ImutInfo>
633 class ImutAVLTreeInOrderIterator {
634   typedef ImutAVLTreeGenericIterator<ImutInfo> InternalIteratorTy;
635   InternalIteratorTy InternalItr;
636
637 public:
638   typedef ImutAVLTree<ImutInfo> TreeTy;
639   typedef ImutAVLTreeInOrderIterator<ImutInfo> _Self;
640
641   ImutAVLTreeInOrderIterator(const TreeTy* Root) : InternalItr(Root) { 
642     if (Root) operator++(); // Advance to first element.
643   }
644   
645   ImutAVLTreeInOrderIterator() : InternalItr() {}
646
647   inline bool operator==(const _Self& x) const {
648     return InternalItr == x.InternalItr;
649   }
650   
651   inline bool operator!=(const _Self& x) const { return !operator==(x); }  
652   
653   inline TreeTy* operator*() { return *InternalItr; }
654   inline TreeTy* operator->() { return *InternalItr; }
655   
656   inline _Self& operator++() { 
657     do ++InternalItr;
658     while (!InternalItr.AtEnd() && 
659            InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft);
660
661     return *this;
662   }
663   
664   inline _Self& operator--() { 
665     do --InternalItr;
666     while (!InternalItr.AtBeginning() && 
667            InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft);
668     
669     return *this;
670   }
671   
672   inline void SkipSubTree() {
673     InternalItr.SkipToParent();
674     
675     while (!InternalItr.AtEnd() &&
676            InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft)
677       ++InternalItr;        
678   }
679 };
680     
681 //===----------------------------------------------------------------------===//    
682 // Trait classes for Profile information.
683 //===----------------------------------------------------------------------===//
684
685 /// Generic profile template.  The default behavior is to invoke the
686 /// profile method of an object.  Specializations for primitive integers
687 /// and generic handling of pointers is done below.
688 template <typename T>
689 struct ImutProfileInfo {
690   typedef const T  value_type;
691   typedef const T& value_type_ref;
692   
693   static inline void Profile(FoldingSetNodeID& ID, value_type_ref X) {
694     X.Profile(ID);
695   }  
696 };
697
698 /// Profile traits for integers.
699 template <typename T>
700 struct ImutProfileInteger {    
701   typedef const T  value_type;
702   typedef const T& value_type_ref;
703   
704   static inline void Profile(FoldingSetNodeID& ID, value_type_ref X) {
705     ID.AddInteger(X);
706   }  
707 };
708
709 #define PROFILE_INTEGER_INFO(X)\
710 template<> struct ImutProfileInfo<X> : ImutProfileInteger<X> {};
711
712 PROFILE_INTEGER_INFO(char)
713 PROFILE_INTEGER_INFO(unsigned char)
714 PROFILE_INTEGER_INFO(short)
715 PROFILE_INTEGER_INFO(unsigned short)
716 PROFILE_INTEGER_INFO(unsigned)
717 PROFILE_INTEGER_INFO(signed)
718 PROFILE_INTEGER_INFO(long)
719 PROFILE_INTEGER_INFO(unsigned long)
720 PROFILE_INTEGER_INFO(long long)
721 PROFILE_INTEGER_INFO(unsigned long long)
722
723 #undef PROFILE_INTEGER_INFO
724
725 /// Generic profile trait for pointer types.  We treat pointers as
726 /// references to unique objects.
727 template <typename T>
728 struct ImutProfileInfo<T*> {
729   typedef const T*   value_type;
730   typedef value_type value_type_ref;
731   
732   static inline void Profile(FoldingSetNodeID &ID, value_type_ref X) {
733     ID.AddPointer(X);
734   }
735 };
736
737 //===----------------------------------------------------------------------===//    
738 // Trait classes that contain element comparison operators and type
739 //  definitions used by ImutAVLTree, ImmutableSet, and ImmutableMap.  These
740 //  inherit from the profile traits (ImutProfileInfo) to include operations
741 //  for element profiling.
742 //===----------------------------------------------------------------------===//
743
744
745 /// ImutContainerInfo - Generic definition of comparison operations for
746 ///   elements of immutable containers that defaults to using
747 ///   std::equal_to<> and std::less<> to perform comparison of elements.
748 template <typename T>
749 struct ImutContainerInfo : public ImutProfileInfo<T> {
750   typedef typename ImutProfileInfo<T>::value_type      value_type;
751   typedef typename ImutProfileInfo<T>::value_type_ref  value_type_ref;
752   typedef value_type      key_type;
753   typedef value_type_ref  key_type_ref;
754   
755   static inline key_type_ref KeyOfValue(value_type_ref D) { return D; }
756   
757   static inline bool isEqual(key_type_ref LHS, key_type_ref RHS) { 
758     return std::equal_to<key_type>()(LHS,RHS);
759   }
760   
761   static inline bool isLess(key_type_ref LHS, key_type_ref RHS) {
762     return std::less<key_type>()(LHS,RHS);
763   }
764 };
765
766 /// ImutContainerInfo - Specialization for pointer values to treat pointers
767 ///  as references to unique objects.  Pointers are thus compared by
768 ///  their addresses.
769 template <typename T>
770 struct ImutContainerInfo<T*> : public ImutProfileInfo<T*> {
771   typedef typename ImutProfileInfo<T*>::value_type      value_type;
772   typedef typename ImutProfileInfo<T*>::value_type_ref  value_type_ref;
773   typedef value_type      key_type;
774   typedef value_type_ref  key_type_ref;
775   
776   static inline key_type_ref KeyOfValue(value_type_ref D) { return D; }
777   
778   static inline bool isEqual(key_type_ref LHS, key_type_ref RHS) {
779     return LHS == RHS;
780   }
781   
782   static inline bool isLess(key_type_ref LHS, key_type_ref RHS) {
783     return LHS < RHS;
784   }
785 };
786
787 //===----------------------------------------------------------------------===//    
788 // Immutable Set
789 //===----------------------------------------------------------------------===//
790
791 template <typename ValT, typename ValInfo = ImutContainerInfo<ValT> >
792 class ImmutableSet {
793 public:
794   typedef typename ValInfo::value_type      value_type;
795   typedef typename ValInfo::value_type_ref  value_type_ref;
796   
797 private:  
798   typedef ImutAVLTree<ValInfo> TreeTy;
799   TreeTy* Root;
800   
801   ImmutableSet(TreeTy* R) : Root(R) {}
802   
803 public:
804   
805   class Factory {
806     typename TreeTy::Factory F;
807     
808   public:
809     Factory() {}
810     
811     ImmutableSet GetEmptySet() { return ImmutableSet(F.GetEmptyTree()); }
812     
813     ImmutableSet Add(ImmutableSet Old, value_type_ref V) {
814       return ImmutableSet(F.Add(Old.Root,V));
815     }
816     
817     ImmutableSet Remove(ImmutableSet Old, value_type_ref V) {
818       return ImmutableSet(F.Remove(Old.Root,V));
819     }
820     
821   private:
822     Factory(const Factory& RHS) {};
823     void operator=(const Factory& RHS) {};    
824   };
825   
826   friend class Factory;
827   
828   bool contains(const value_type_ref V) const {
829     return Root ? Root->contains(V) : false;
830   }
831   
832   bool operator==(ImmutableSet RHS) const {
833     return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root;
834   }
835   
836   bool operator!=(ImmutableSet RHS) const {
837     return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root;
838   }
839   
840   bool isEmpty() const { return !Root; }
841   
842   template <typename Callback>
843   void foreach(Callback& C) { if (Root) Root->foreach(C); }
844   
845   template <typename Callback>
846   void foreach() { if (Root) { Callback C; Root->foreach(C); } }
847   
848   //===--------------------------------------------------===//    
849   // For testing.
850   //===--------------------------------------------------===//  
851   
852   void verify() const { if (Root) Root->verify(); }
853   unsigned getHeight() const { return Root ? Root->getHeight() : 0; }
854 };
855
856 } // end namespace llvm
857
858 #endif