LLVM API Documentation

ImmutableMap.h

Go to the documentation of this file.
00001 //===--- ImmutableMap.h - Immutable (functional) map 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 ImmutableMap class.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #ifndef LLVM_ADT_IMMAP_H
00015 #define LLVM_ADT_IMMAP_H
00016 
00017 #include "llvm/ADT/ImmutableSet.h"
00018 
00019 namespace llvm {
00020 
00021 /// ImutKeyValueInfo -Traits class used by ImmutableMap.  While both the first and
00022 /// second elements in a pair are used to generate profile information,
00023 /// only the first element (the key) is used by isEqual and isLess.
00024 template <typename T, typename S>
00025 struct ImutKeyValueInfo {
00026   typedef const std::pair<T,S> value_type;
00027   typedef const value_type& value_type_ref;
00028   typedef const T   key_type;
00029   typedef const T&  key_type_ref;
00030   typedef const S   data_type;
00031   typedef const S&  data_type_ref;
00032 
00033   static inline key_type_ref KeyOfValue(value_type_ref V) {
00034     return V.first;
00035   }
00036 
00037   static inline data_type_ref DataOfValue(value_type_ref V) {
00038     return V.second;
00039   }
00040 
00041   static inline bool isEqual(key_type_ref L, key_type_ref R) {
00042     return ImutContainerInfo<T>::isEqual(L,R);
00043   }
00044   static inline bool isLess(key_type_ref L, key_type_ref R) {
00045     return ImutContainerInfo<T>::isLess(L,R);
00046   }
00047 
00048   static inline bool isDataEqual(data_type_ref L, data_type_ref R) {
00049     return ImutContainerInfo<S>::isEqual(L,R);
00050   }
00051 
00052   static inline void Profile(FoldingSetNodeID& ID, value_type_ref V) {
00053     ImutContainerInfo<T>::Profile(ID, V.first);
00054     ImutContainerInfo<S>::Profile(ID, V.second);
00055   }
00056 };
00057 
00058 
00059 template <typename KeyT, typename ValT,
00060           typename ValInfo = ImutKeyValueInfo<KeyT,ValT> >
00061 class ImmutableMap {
00062 public:
00063   typedef typename ValInfo::value_type      value_type;
00064   typedef typename ValInfo::value_type_ref  value_type_ref;
00065   typedef typename ValInfo::key_type        key_type;
00066   typedef typename ValInfo::key_type_ref    key_type_ref;
00067   typedef typename ValInfo::data_type       data_type;
00068   typedef typename ValInfo::data_type_ref   data_type_ref;
00069   typedef ImutAVLTree<ValInfo>              TreeTy;
00070 
00071 private:
00072   TreeTy* Root;
00073 
00074 public:
00075   /// Constructs a map from a pointer to a tree root.  In general one
00076   /// should use a Factory object to create maps instead of directly
00077   /// invoking the constructor, but there are cases where make this
00078   /// constructor public is useful.
00079   explicit ImmutableMap(const TreeTy* R) : Root(const_cast<TreeTy*>(R)) {}
00080 
00081   class Factory {
00082     typename TreeTy::Factory F;
00083 
00084   public:
00085     Factory() {}
00086 
00087     Factory(BumpPtrAllocator& Alloc)
00088       : F(Alloc) {}
00089 
00090     ImmutableMap GetEmptyMap() { return ImmutableMap(F.GetEmptyTree()); }
00091 
00092     ImmutableMap Add(ImmutableMap Old, key_type_ref K, data_type_ref D) {
00093       return ImmutableMap(F.Add(Old.Root,
00094                                 std::make_pair<key_type,data_type>(K,D)));
00095     }
00096 
00097     ImmutableMap Remove(ImmutableMap Old, key_type_ref K) {
00098       return ImmutableMap(F.Remove(Old.Root,K));
00099     }
00100 
00101   private:
00102     Factory(const Factory& RHS) {};
00103     void operator=(const Factory& RHS) {};
00104   };
00105 
00106   friend class Factory;
00107 
00108   bool contains(key_type_ref K) const {
00109     return Root ? Root->contains(K) : false;
00110   }
00111 
00112 
00113   bool operator==(ImmutableMap RHS) const {
00114     return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root;
00115   }
00116 
00117   bool operator!=(ImmutableMap RHS) const {
00118     return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root;
00119   }
00120 
00121   TreeTy* getRoot() const { return Root; }
00122 
00123   bool isEmpty() const { return !Root; }
00124 
00125   //===--------------------------------------------------===//
00126   // Foreach - A limited form of map iteration.
00127   //===--------------------------------------------------===//
00128 
00129 private:
00130   template <typename Callback>
00131   struct CBWrapper {
00132     Callback C;
00133     void operator()(value_type_ref V) { C(V.first,V.second); }
00134   };
00135 
00136   template <typename Callback>
00137   struct CBWrapperRef {
00138     Callback &C;
00139     CBWrapperRef(Callback& c) : C(c) {}
00140 
00141     void operator()(value_type_ref V) { C(V.first,V.second); }
00142   };
00143 
00144 public:
00145   template <typename Callback>
00146   void foreach(Callback& C) {
00147     if (Root) {
00148       CBWrapperRef<Callback> CB(C);
00149       Root->foreach(CB);
00150     }
00151   }
00152 
00153   template <typename Callback>
00154   void foreach() {
00155     if (Root) {
00156       CBWrapper<Callback> CB;
00157       Root->foreach(CB);
00158     }
00159   }
00160 
00161   //===--------------------------------------------------===//
00162   // For testing.
00163   //===--------------------------------------------------===//
00164 
00165   void verify() const { if (Root) Root->verify(); }
00166 
00167   //===--------------------------------------------------===//
00168   // Iterators.
00169   //===--------------------------------------------------===//
00170 
00171   class iterator {
00172     typename TreeTy::iterator itr;
00173 
00174     iterator() {}
00175     iterator(TreeTy* t) : itr(t) {}
00176     friend class ImmutableMap;
00177 
00178   public:
00179     value_type_ref operator*() const { return itr->getValue(); }
00180     value_type*    operator->() const { return &itr->getValue(); }
00181 
00182     key_type_ref getKey() const { return itr->getValue().first; }
00183     data_type_ref getData() const { return itr->getValue().second; }
00184 
00185 
00186     iterator& operator++() { ++itr; return *this; }
00187     iterator  operator++(int) { iterator tmp(*this); ++itr; return tmp; }
00188     iterator& operator--() { --itr; return *this; }
00189     iterator  operator--(int) { iterator tmp(*this); --itr; return tmp; }
00190     bool operator==(const iterator& RHS) const { return RHS.itr == itr; }
00191     bool operator!=(const iterator& RHS) const { return RHS.itr != itr; }
00192   };
00193 
00194   iterator begin() const { return iterator(Root); }
00195   iterator end() const { return iterator(); }
00196 
00197   data_type* lookup(key_type_ref K) const {
00198     if (Root) {
00199       TreeTy* T = Root->find(K);
00200       if (T) return &T->getValue().second;
00201     }
00202 
00203     return 0;
00204   }
00205 
00206   //===--------------------------------------------------===//
00207   // Utility methods.
00208   //===--------------------------------------------------===//
00209 
00210   inline unsigned getHeight() const { return Root ? Root->getHeight() : 0; }
00211 
00212   static inline void Profile(FoldingSetNodeID& ID, const ImmutableMap& M) {
00213     ID.AddPointer(M.Root);
00214   }
00215 
00216   inline void Profile(FoldingSetNodeID& ID) const {
00217     return Profile(ID,*this);
00218   }
00219 };
00220 
00221 } // end namespace llvm
00222 
00223 #endif