Removed spurious forward declaration to a structure that will no longer be used.
[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                unsigned H, value_type_ref V) {    
205     ID.AddPointer(L);
206     ID.AddPointer(R);
207     ID.AddInteger(H);
208     ImutInfo::Profile(ID,V);
209   }
210   
211 public:
212   
213   void Profile(FoldingSetNodeID& ID) {
214     Profile(ID,getSafeLeft(),getRight(),getHeight(),getValue());    
215   }
216   
217   //===----------------------------------------------------===//    
218   // Internal methods (node manipulation; used by Factory).
219   //===----------------------------------------------------===//
220   
221 private:
222   
223   ImutAVLTree(ImutAVLTree* l, ImutAVLTree* r, value_type_ref v, unsigned height)
224   : Left(reinterpret_cast<uintptr_t>(l) | 0x1),
225   Right(r), Height(height), Value(v) {}
226   
227   bool isMutable() const { return Left & 0x1; }
228   
229   ImutAVLTree* getSafeLeft() const { 
230     return reinterpret_cast<ImutAVLTree*>(Left & ~0x1);
231   }
232   
233   // Mutating operations.  A tree root can be manipulated as long as
234   // its reference has not "escaped" from internal methods of a
235   // factory object (see below).  When a tree pointer is externally
236   // viewable by client code, the internal "mutable bit" is cleared
237   // to mark the tree immutable.  Note that a tree that still has
238   // its mutable bit set may have children (subtrees) that are themselves
239   // immutable.
240   
241   void RemoveMutableFlag() {
242     assert (Left & 0x1 && "Mutable flag already removed.");
243     Left &= ~0x1;
244   }
245   
246   void setLeft(ImutAVLTree* NewLeft) {
247     assert (isMutable());
248     Left = reinterpret_cast<uintptr_t>(NewLeft) | 0x1;
249   }
250   
251   void setRight(ImutAVLTree* NewRight) {
252     assert (isMutable());
253     Right = NewRight;
254   }
255   
256   void setHeight(unsigned h) {
257     assert (isMutable());
258     Height = h;
259   }
260 };
261
262 //===----------------------------------------------------------------------===//    
263 // Immutable AVL-Tree Factory class.
264 //===----------------------------------------------------------------------===//
265
266 template <typename ImutInfo >  
267 class ImutAVLFactory {
268   typedef ImutAVLTree<ImutInfo> TreeTy;
269   typedef typename TreeTy::value_type_ref value_type_ref;
270   typedef typename TreeTy::key_type_ref   key_type_ref;
271   
272   typedef FoldingSet<TreeTy> CacheTy;
273   
274   CacheTy Cache;  
275   BumpPtrAllocator Allocator;    
276   
277   //===--------------------------------------------------===//    
278   // Public interface.
279   //===--------------------------------------------------===//
280   
281 public:
282   ImutAVLFactory() {}
283   
284   TreeTy* Add(TreeTy* T, value_type_ref V) {
285     T = Add_internal(V,T);
286     MarkImmutable(T);
287     return T;
288   }
289   
290   TreeTy* Remove(TreeTy* T, key_type_ref V) {
291     T = Remove_internal(V,T);
292     MarkImmutable(T);
293     return T;
294   }
295   
296   TreeTy* GetEmptyTree() const { return NULL; }
297   
298   //===--------------------------------------------------===//    
299   // A bunch of quick helper functions used for reasoning
300   // about the properties of trees and their children.
301   // These have succinct names so that the balancing code
302   // is as terse (and readable) as possible.
303   //===--------------------------------------------------===//
304 private:
305   
306   bool isEmpty(TreeTy* T) const {
307     return !T;
308   }
309   
310   unsigned Height(TreeTy* T) const {
311     return T ? T->getHeight() : 0;
312   }
313   
314   TreeTy* Left(TreeTy* T) const {
315     assert (T);
316     return T->getSafeLeft();
317   }
318   
319   TreeTy* Right(TreeTy* T) const {
320     assert (T);
321     return T->getRight();
322   }
323   
324   value_type_ref Value(TreeTy* T) const {
325     assert (T);
326     return T->Value;
327   }
328   
329   unsigned IncrementHeight(TreeTy* L, TreeTy* R) const {
330     unsigned hl = Height(L);
331     unsigned hr = Height(R);
332     return ( hl > hr ? hl : hr ) + 1;
333   }
334   
335   //===--------------------------------------------------===//    
336   // "CreateNode" is used to generate new tree roots that link
337   // to other trees.  The functon may also simply move links
338   // in an existing root if that root is still marked mutable.
339   // This is necessary because otherwise our balancing code
340   // would leak memory as it would create nodes that are
341   // then discarded later before the finished tree is
342   // returned to the caller.
343   //===--------------------------------------------------===//
344   
345   TreeTy* CreateNode(TreeTy* L, value_type_ref V, TreeTy* R) {
346     FoldingSetNodeID ID;      
347     unsigned height = IncrementHeight(L,R);
348     
349     TreeTy::Profile(ID,L,R,height,V);      
350     void* InsertPos;
351     
352     if (TreeTy* T = Cache.FindNodeOrInsertPos(ID,InsertPos))
353       return T;
354     
355     assert (InsertPos != NULL);
356     
357     // FIXME: more intelligent calculation of alignment.
358     TreeTy* T = (TreeTy*) Allocator.Allocate(sizeof(*T),16);
359     new (T) TreeTy(L,R,V,height);
360     
361     Cache.InsertNode(T,InsertPos);
362     return T;      
363   }
364   
365   TreeTy* CreateNode(TreeTy* L, TreeTy* OldTree, TreeTy* R) {      
366     assert (!isEmpty(OldTree));
367     
368     if (OldTree->isMutable()) {
369       OldTree->setLeft(L);
370       OldTree->setRight(R);
371       OldTree->setHeight(IncrementHeight(L,R));
372       return OldTree;
373     }
374     else return CreateNode(L, Value(OldTree), R);
375   }
376   
377   /// Balance - Used by Add_internal and Remove_internal to
378   ///  balance a newly created tree.
379   TreeTy* Balance(TreeTy* L, value_type_ref V, TreeTy* R) {
380     
381     unsigned hl = Height(L);
382     unsigned hr = Height(R);
383     
384     if (hl > hr + 2) {
385       assert (!isEmpty(L) &&
386               "Left tree cannot be empty to have a height >= 2.");
387       
388       TreeTy* LL = Left(L);
389       TreeTy* LR = Right(L);
390       
391       if (Height(LL) >= Height(LR))
392         return CreateNode(LL, L, CreateNode(LR,V,R));
393       
394       assert (!isEmpty(LR) &&
395               "LR cannot be empty because it has a height >= 1.");
396       
397       TreeTy* LRL = Left(LR);
398       TreeTy* LRR = Right(LR);
399       
400       return CreateNode(CreateNode(LL,L,LRL), LR, CreateNode(LRR,V,R));                              
401     }
402     else if (hr > hl + 2) {
403       assert (!isEmpty(R) &&
404               "Right tree cannot be empty to have a height >= 2.");
405       
406       TreeTy* RL = Left(R);
407       TreeTy* RR = Right(R);
408       
409       if (Height(RR) >= Height(RL))
410         return CreateNode(CreateNode(L,V,RL), R, RR);
411       
412       assert (!isEmpty(RL) &&
413               "RL cannot be empty because it has a height >= 1.");
414       
415       TreeTy* RLL = Left(RL);
416       TreeTy* RLR = Right(RL);
417       
418       return CreateNode(CreateNode(L,V,RLL), RL, CreateNode(RLR,R,RR));
419     }
420     else
421       return CreateNode(L,V,R);
422   }
423   
424   /// Add_internal - Creates a new tree that includes the specified
425   ///  data and the data from the original tree.  If the original tree
426   ///  already contained the data item, the original tree is returned.
427   TreeTy* Add_internal(value_type_ref V, TreeTy* T) {
428     if (isEmpty(T))
429       return CreateNode(T, V, T);
430     
431     assert (!T->isMutable());
432     
433     key_type_ref K = ImutInfo::KeyOfValue(V);
434     key_type_ref KCurrent = ImutInfo::KeyOfValue(Value(T));
435     
436     if (ImutInfo::isEqual(K,KCurrent))
437       return CreateNode(Left(T), V, Right(T));
438     else if (ImutInfo::isLess(K,KCurrent))
439       return Balance(Add_internal(V,Left(T)), Value(T), Right(T));
440     else
441       return Balance(Left(T), Value(T), Add_internal(V,Right(T)));
442   }
443   
444   /// Remove_interal - Creates a new tree that includes all the data
445   ///  from the original tree except the specified data.  If the
446   ///  specified data did not exist in the original tree, the original
447   ///  tree is returned.
448   TreeTy* Remove_internal(key_type_ref K, TreeTy* T) {
449     if (isEmpty(T))
450       return T;
451     
452     assert (!T->isMutable());
453     
454     key_type_ref KCurrent = ImutInfo::KeyOfValue(Value(T));
455     
456     if (ImutInfo::isEqual(K,KCurrent))
457       return CombineLeftRightTrees(Left(T),Right(T));
458     else if (ImutInfo::isLess(K,KCurrent))
459       return Balance(Remove_internal(K,Left(T)), Value(T), Right(T));
460     else
461       return Balance(Left(T), Value(T), Remove_internal(K,Right(T)));
462   }
463   
464   TreeTy* CombineLeftRightTrees(TreeTy* L, TreeTy* R) {
465     if (isEmpty(L)) return R;      
466     if (isEmpty(R)) return L;
467     
468     TreeTy* OldNode;          
469     TreeTy* NewRight = RemoveMinBinding(R,OldNode);
470     return Balance(L,Value(OldNode),NewRight);
471   }
472   
473   TreeTy* RemoveMinBinding(TreeTy* T, TreeTy*& NodeRemoved) {
474     assert (!isEmpty(T));
475     
476     if (isEmpty(Left(T))) {
477       NodeRemoved = T;
478       return Right(T);
479     }
480     
481     return Balance(RemoveMinBinding(Left(T),NodeRemoved),Value(T),Right(T));
482   }    
483   
484   /// MarkImmutable - Clears the mutable bits of a root and all of its
485   ///  descendants.
486   void MarkImmutable(TreeTy* T) {
487     if (!T || !T->isMutable())
488       return;
489     
490     T->RemoveMutableFlag();
491     MarkImmutable(Left(T));
492     MarkImmutable(Right(T));
493   }
494 };
495   
496   
497 //===----------------------------------------------------------------------===//    
498 // Immutable AVL-Tree Iterators.
499 //===----------------------------------------------------------------------===//  
500
501 template <typename ImutInfo>
502 class ImutAVLTreeGenericIterator {
503   SmallVector<uintptr_t,20> stack;
504 public:
505   enum VisitFlag { VisitedNone=0x0, VisitedLeft=0x1, VisitedRight=0x3, 
506                    Flags=0x3 };
507   
508   typedef ImutAVLTree<ImutInfo> TreeTy;      
509   typedef ImutAVLTreeGenericIterator<ImutInfo> _Self;
510
511   inline ImutAVLTreeGenericIterator() {}
512   inline ImutAVLTreeGenericIterator(const TreeTy* Root) {
513     if (Root) stack.push_back(reinterpret_cast<uintptr_t>(Root));
514   }  
515   
516   TreeTy* operator*() const {
517     assert (!stack.empty());    
518     return reinterpret_cast<TreeTy*>(stack.back() & ~Flags);
519   }
520   
521   uintptr_t getVisitState() {
522     assert (!stack.empty());
523     return stack.back() & Flags;
524   }
525   
526   
527   bool AtEnd() const { return stack.empty(); }
528
529   bool AtBeginning() const { 
530     return stack.size() == 1 && getVisitState() == VisitedNone;
531   }
532   
533   void SkipToParent() {
534     assert (!stack.empty());
535     stack.pop_back();
536     
537     if (stack.empty())
538       return;
539     
540     switch (getVisitState()) {
541       case VisitedNone:
542         stack.back() |= VisitedLeft;
543         break;
544       case VisitedLeft:
545         stack.back() |= VisitedRight;
546         break;
547       default:
548         assert (false && "Unreachable.");            
549     }
550   }
551   
552   inline bool operator==(const _Self& x) const {
553     if (stack.size() != x.stack.size())
554       return false;
555     
556     for (unsigned i = 0 ; i < stack.size(); i++)
557       if (stack[i] != x.stack[i])
558         return false;
559     
560     return true;
561   }
562   
563   inline bool operator!=(const _Self& x) const { return !operator==(x); }  
564   
565   _Self& operator++() {
566     assert (!stack.empty());
567     
568     TreeTy* Current = reinterpret_cast<TreeTy*>(stack.back() & ~Flags);
569     assert (Current);
570     
571     switch (getVisitState()) {
572       case VisitedNone:
573         if (TreeTy* L = Current->getLeft())
574           stack.push_back(reinterpret_cast<uintptr_t>(L));
575         else
576           stack.back() |= VisitedLeft;
577         
578         break;
579         
580       case VisitedLeft:
581         if (TreeTy* R = Current->getRight())
582           stack.push_back(reinterpret_cast<uintptr_t>(R));
583         else
584           stack.back() |= VisitedRight;
585         
586         break;
587         
588       case VisitedRight:
589         SkipToParent();        
590         break;
591         
592       default:
593         assert (false && "Unreachable.");
594     }
595     
596     return *this;
597   }
598   
599   _Self& operator--() {
600     assert (!stack.empty());
601     
602     TreeTy* Current = reinterpret_cast<TreeTy*>(stack.back() & ~Flags);
603     assert (Current);
604     
605     switch (getVisitState()) {
606       case VisitedNone:
607         stack.pop_back();
608         break;
609         
610       case VisitedLeft:                
611         stack.back() &= ~Flags; // Set state to "VisitedNone."
612         
613         if (TreeTy* L = Current->getLeft())
614           stack.push_back(reinterpret_cast<uintptr_t>(L) | VisitedRight);
615           
616         break;
617         
618       case VisitedRight:        
619         stack.back() &= ~Flags;
620         stack.back() |= VisitedLeft;
621         
622         if (TreeTy* R = Current->getRight())
623           stack.push_back(reinterpret_cast<uintptr_t>(R) | VisitedRight);
624           
625         break;
626         
627       default:
628         assert (false && "Unreachable.");
629     }
630     
631     return *this;
632   }
633 };
634   
635 template <typename ImutInfo>
636 class ImutAVLTreeInOrderIterator {
637   typedef ImutAVLTreeGenericIterator<ImutInfo> InternalIteratorTy;
638   InternalIteratorTy InternalItr;
639
640 public:
641   typedef ImutAVLTree<ImutInfo> TreeTy;
642   typedef ImutAVLTreeInOrderIterator<ImutInfo> _Self;
643
644   ImutAVLTreeInOrderIterator(const TreeTy* Root) : InternalItr(Root) { 
645     if (Root) operator++(); // Advance to first element.
646   }
647   
648   ImutAVLTreeInOrderIterator() : InternalItr() {}
649
650   inline bool operator==(const _Self& x) const {
651     return InternalItr == x.InternalItr;
652   }
653   
654   inline bool operator!=(const _Self& x) const { return !operator==(x); }  
655   
656   inline TreeTy* operator*() { return *InternalItr; }
657   inline TreeTy* operator->() { return *InternalItr; }
658   
659   inline _Self& operator++() { 
660     do ++InternalItr;
661     while (!InternalItr.AtEnd() && 
662            InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft);
663
664     return *this;
665   }
666   
667   inline _Self& operator--() { 
668     do --InternalItr;
669     while (!InternalItr.AtBeginning() && 
670            InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft);
671     
672     return *this;
673   }
674   
675   inline void SkipSubTree() {
676     InternalItr.SkipToParent();
677     
678     while (!InternalItr.AtEnd() &&
679            InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft)
680       ++InternalItr;        
681   }
682 };
683     
684 //===----------------------------------------------------------------------===//    
685 // Trait classes for Profile information.
686 //===----------------------------------------------------------------------===//
687
688 /// Generic profile template.  The default behavior is to invoke the
689 /// profile method of an object.  Specializations for primitive integers
690 /// and generic handling of pointers is done below.
691 template <typename T>
692 struct ImutProfileInfo {
693   typedef const T  value_type;
694   typedef const T& value_type_ref;
695   
696   static inline void Profile(FoldingSetNodeID& ID, value_type_ref X) {
697     X.Profile(ID);
698   }  
699 };
700
701 /// Profile traits for integers.
702 template <typename T>
703 struct ImutProfileInteger {    
704   typedef const T  value_type;
705   typedef const T& value_type_ref;
706   
707   static inline void Profile(FoldingSetNodeID& ID, value_type_ref X) {
708     ID.AddInteger(X);
709   }  
710 };
711
712 #define PROFILE_INTEGER_INFO(X)\
713 template<> struct ImutProfileInfo<X> : ImutProfileInteger<X> {};
714
715 PROFILE_INTEGER_INFO(char)
716 PROFILE_INTEGER_INFO(unsigned char)
717 PROFILE_INTEGER_INFO(short)
718 PROFILE_INTEGER_INFO(unsigned short)
719 PROFILE_INTEGER_INFO(unsigned)
720 PROFILE_INTEGER_INFO(signed)
721 PROFILE_INTEGER_INFO(long)
722 PROFILE_INTEGER_INFO(unsigned long)
723 PROFILE_INTEGER_INFO(long long)
724 PROFILE_INTEGER_INFO(unsigned long long)
725
726 #undef PROFILE_INTEGER_INFO
727
728 /// Generic profile trait for pointer types.  We treat pointers as
729 /// references to unique objects.
730 template <typename T>
731 struct ImutProfileInfo<T*> {
732   typedef const T*   value_type;
733   typedef value_type value_type_ref;
734   
735   static inline void Profile(FoldingSetNodeID &ID, value_type_ref X) {
736     ID.AddPointer(X);
737   }
738 };
739
740 //===----------------------------------------------------------------------===//    
741 // Trait classes that contain element comparison operators and type
742 //  definitions used by ImutAVLTree, ImmutableSet, and ImmutableMap.  These
743 //  inherit from the profile traits (ImutProfileInfo) to include operations
744 //  for element profiling.
745 //===----------------------------------------------------------------------===//
746
747
748 /// ImutContainerInfo - Generic definition of comparison operations for
749 ///   elements of immutable containers that defaults to using
750 ///   std::equal_to<> and std::less<> to perform comparison of elements.
751 template <typename T>
752 struct ImutContainerInfo : public ImutProfileInfo<T> {
753   typedef typename ImutProfileInfo<T>::value_type      value_type;
754   typedef typename ImutProfileInfo<T>::value_type_ref  value_type_ref;
755   typedef value_type      key_type;
756   typedef value_type_ref  key_type_ref;
757   
758   static inline key_type_ref KeyOfValue(value_type_ref D) { return D; }
759   
760   static inline bool isEqual(key_type_ref LHS, key_type_ref RHS) { 
761     return std::equal_to<key_type>()(LHS,RHS);
762   }
763   
764   static inline bool isLess(key_type_ref LHS, key_type_ref RHS) {
765     return std::less<key_type>()(LHS,RHS);
766   }
767 };
768
769 /// ImutContainerInfo - Specialization for pointer values to treat pointers
770 ///  as references to unique objects.  Pointers are thus compared by
771 ///  their addresses.
772 template <typename T>
773 struct ImutContainerInfo<T*> : public ImutProfileInfo<T*> {
774   typedef typename ImutProfileInfo<T*>::value_type      value_type;
775   typedef typename ImutProfileInfo<T*>::value_type_ref  value_type_ref;
776   typedef value_type      key_type;
777   typedef value_type_ref  key_type_ref;
778   
779   static inline key_type_ref KeyOfValue(value_type_ref D) { return D; }
780   
781   static inline bool isEqual(key_type_ref LHS, key_type_ref RHS) {
782     return LHS == RHS;
783   }
784   
785   static inline bool isLess(key_type_ref LHS, key_type_ref RHS) {
786     return LHS < RHS;
787   }
788 };
789
790 //===----------------------------------------------------------------------===//    
791 // Immutable Set
792 //===----------------------------------------------------------------------===//
793
794 template <typename ValT, typename ValInfo = ImutContainerInfo<ValT> >
795 class ImmutableSet {
796 public:
797   typedef typename ValInfo::value_type      value_type;
798   typedef typename ValInfo::value_type_ref  value_type_ref;
799   
800 private:  
801   typedef ImutAVLTree<ValInfo> TreeTy;
802   TreeTy* Root;
803   
804   ImmutableSet(TreeTy* R) : Root(R) {}
805   
806 public:
807   
808   class Factory {
809     typename TreeTy::Factory F;
810     
811   public:
812     Factory() {}
813     
814     ImmutableSet GetEmptySet() { return ImmutableSet(F.GetEmptyTree()); }
815     
816     ImmutableSet Add(ImmutableSet Old, value_type_ref V) {
817       return ImmutableSet(F.Add(Old.Root,V));
818     }
819     
820     ImmutableSet Remove(ImmutableSet Old, value_type_ref V) {
821       return ImmutableSet(F.Remove(Old.Root,V));
822     }
823     
824   private:
825     Factory(const Factory& RHS) {};
826     void operator=(const Factory& RHS) {};    
827   };
828   
829   friend class Factory;
830   
831   bool contains(const value_type_ref V) const {
832     return Root ? Root->contains(V) : false;
833   }
834   
835   bool operator==(ImmutableSet RHS) const {
836     return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root;
837   }
838   
839   bool operator!=(ImmutableSet RHS) const {
840     return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root;
841   }
842   
843   bool isEmpty() const { return !Root; }
844   
845   template <typename Callback>
846   void foreach(Callback& C) { if (Root) Root->foreach(C); }
847   
848   template <typename Callback>
849   void foreach() { if (Root) { Callback C; Root->foreach(C); } }
850   
851   //===--------------------------------------------------===//    
852   // For testing.
853   //===--------------------------------------------------===//  
854   
855   void verify() const { if (Root) Root->verify(); }
856   unsigned getHeight() const { return Root ? Root->getHeight() : 0; }
857 };
858
859 } // end namespace llvm
860
861 #endif