LLVM API Documentation
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