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_IMMUTABLEMAP_H 00015 #define LLVM_ADT_IMMUTABLEMAP_H 00016 00017 #include "llvm/ADT/ImmutableSet.h" 00018 00019 namespace llvm { 00020 00021 /// ImutKeyValueInfo -Traits class used by ImmutableMap. While both the first 00022 /// and 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 protected: 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 if (Root) { Root->retain(); } 00081 } 00082 ImmutableMap(const ImmutableMap &X) : Root(X.Root) { 00083 if (Root) { Root->retain(); } 00084 } 00085 ImmutableMap &operator=(const ImmutableMap &X) { 00086 if (Root != X.Root) { 00087 if (X.Root) { X.Root->retain(); } 00088 if (Root) { Root->release(); } 00089 Root = X.Root; 00090 } 00091 return *this; 00092 } 00093 ~ImmutableMap() { 00094 if (Root) { Root->release(); } 00095 } 00096 00097 class Factory { 00098 typename TreeTy::Factory F; 00099 const bool Canonicalize; 00100 00101 public: 00102 Factory(bool canonicalize = true) 00103 : Canonicalize(canonicalize) {} 00104 00105 Factory(BumpPtrAllocator& Alloc, bool canonicalize = true) 00106 : F(Alloc), Canonicalize(canonicalize) {} 00107 00108 ImmutableMap getEmptyMap() { return ImmutableMap(F.getEmptyTree()); } 00109 00110 ImmutableMap add(ImmutableMap Old, key_type_ref K, data_type_ref D) { 00111 TreeTy *T = F.add(Old.Root, std::pair<key_type,data_type>(K,D)); 00112 return ImmutableMap(Canonicalize ? F.getCanonicalTree(T): T); 00113 } 00114 00115 ImmutableMap remove(ImmutableMap Old, key_type_ref K) { 00116 TreeTy *T = F.remove(Old.Root,K); 00117 return ImmutableMap(Canonicalize ? F.getCanonicalTree(T): T); 00118 } 00119 00120 typename TreeTy::Factory *getTreeFactory() const { 00121 return const_cast<typename TreeTy::Factory *>(&F); 00122 } 00123 00124 private: 00125 Factory(const Factory& RHS) LLVM_DELETED_FUNCTION; 00126 void operator=(const Factory& RHS) LLVM_DELETED_FUNCTION; 00127 }; 00128 00129 bool contains(key_type_ref K) const { 00130 return Root ? Root->contains(K) : false; 00131 } 00132 00133 bool operator==(const ImmutableMap &RHS) const { 00134 return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root; 00135 } 00136 00137 bool operator!=(const ImmutableMap &RHS) const { 00138 return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root; 00139 } 00140 00141 TreeTy *getRoot() const { 00142 if (Root) { Root->retain(); } 00143 return Root; 00144 } 00145 00146 TreeTy *getRootWithoutRetain() const { 00147 return Root; 00148 } 00149 00150 void manualRetain() { 00151 if (Root) Root->retain(); 00152 } 00153 00154 void manualRelease() { 00155 if (Root) Root->release(); 00156 } 00157 00158 bool isEmpty() const { return !Root; } 00159 00160 //===--------------------------------------------------===// 00161 // Foreach - A limited form of map iteration. 00162 //===--------------------------------------------------===// 00163 00164 private: 00165 template <typename Callback> 00166 struct CBWrapper { 00167 Callback C; 00168 void operator()(value_type_ref V) { C(V.first,V.second); } 00169 }; 00170 00171 template <typename Callback> 00172 struct CBWrapperRef { 00173 Callback &C; 00174 CBWrapperRef(Callback& c) : C(c) {} 00175 00176 void operator()(value_type_ref V) { C(V.first,V.second); } 00177 }; 00178 00179 public: 00180 template <typename Callback> 00181 void foreach(Callback& C) { 00182 if (Root) { 00183 CBWrapperRef<Callback> CB(C); 00184 Root->foreach(CB); 00185 } 00186 } 00187 00188 template <typename Callback> 00189 void foreach() { 00190 if (Root) { 00191 CBWrapper<Callback> CB; 00192 Root->foreach(CB); 00193 } 00194 } 00195 00196 //===--------------------------------------------------===// 00197 // For testing. 00198 //===--------------------------------------------------===// 00199 00200 void verify() const { if (Root) Root->verify(); } 00201 00202 //===--------------------------------------------------===// 00203 // Iterators. 00204 //===--------------------------------------------------===// 00205 00206 class iterator { 00207 typename TreeTy::iterator itr; 00208 00209 iterator() {} 00210 iterator(TreeTy* t) : itr(t) {} 00211 friend class ImmutableMap; 00212 00213 public: 00214 typedef ptrdiff_t difference_type; 00215 typedef typename ImmutableMap<KeyT,ValT,ValInfo>::value_type value_type; 00216 typedef typename ImmutableMap<KeyT,ValT,ValInfo>::value_type_ref reference; 00217 typedef typename iterator::value_type *pointer; 00218 typedef std::bidirectional_iterator_tag iterator_category; 00219 00220 typename iterator::reference operator*() const { return itr->getValue(); } 00221 typename iterator::pointer operator->() const { return &itr->getValue(); } 00222 00223 key_type_ref getKey() const { return itr->getValue().first; } 00224 data_type_ref getData() const { return itr->getValue().second; } 00225 00226 iterator& operator++() { ++itr; return *this; } 00227 iterator operator++(int) { iterator tmp(*this); ++itr; return tmp; } 00228 iterator& operator--() { --itr; return *this; } 00229 iterator operator--(int) { iterator tmp(*this); --itr; return tmp; } 00230 00231 bool operator==(const iterator& RHS) const { return RHS.itr == itr; } 00232 bool operator!=(const iterator& RHS) const { return RHS.itr != itr; } 00233 }; 00234 00235 iterator begin() const { return iterator(Root); } 00236 iterator end() const { return iterator(); } 00237 00238 data_type* lookup(key_type_ref K) const { 00239 if (Root) { 00240 TreeTy* T = Root->find(K); 00241 if (T) return &T->getValue().second; 00242 } 00243 00244 return nullptr; 00245 } 00246 00247 /// getMaxElement - Returns the <key,value> pair in the ImmutableMap for 00248 /// which key is the highest in the ordering of keys in the map. This 00249 /// method returns NULL if the map is empty. 00250 value_type* getMaxElement() const { 00251 return Root ? &(Root->getMaxElement()->getValue()) : nullptr; 00252 } 00253 00254 //===--------------------------------------------------===// 00255 // Utility methods. 00256 //===--------------------------------------------------===// 00257 00258 unsigned getHeight() const { return Root ? Root->getHeight() : 0; } 00259 00260 static inline void Profile(FoldingSetNodeID& ID, const ImmutableMap& M) { 00261 ID.AddPointer(M.Root); 00262 } 00263 00264 inline void Profile(FoldingSetNodeID& ID) const { 00265 return Profile(ID,*this); 00266 } 00267 }; 00268 00269 // NOTE: This will possibly become the new implementation of ImmutableMap some day. 00270 template <typename KeyT, typename ValT, 00271 typename ValInfo = ImutKeyValueInfo<KeyT,ValT> > 00272 class ImmutableMapRef { 00273 public: 00274 typedef typename ValInfo::value_type value_type; 00275 typedef typename ValInfo::value_type_ref value_type_ref; 00276 typedef typename ValInfo::key_type key_type; 00277 typedef typename ValInfo::key_type_ref key_type_ref; 00278 typedef typename ValInfo::data_type data_type; 00279 typedef typename ValInfo::data_type_ref data_type_ref; 00280 typedef ImutAVLTree<ValInfo> TreeTy; 00281 typedef typename TreeTy::Factory FactoryTy; 00282 00283 protected: 00284 TreeTy *Root; 00285 FactoryTy *Factory; 00286 00287 public: 00288 /// Constructs a map from a pointer to a tree root. In general one 00289 /// should use a Factory object to create maps instead of directly 00290 /// invoking the constructor, but there are cases where make this 00291 /// constructor public is useful. 00292 explicit ImmutableMapRef(const TreeTy* R, FactoryTy *F) 00293 : Root(const_cast<TreeTy*>(R)), 00294 Factory(F) { 00295 if (Root) { Root->retain(); } 00296 } 00297 00298 explicit ImmutableMapRef(const ImmutableMap<KeyT, ValT> &X, 00299 typename ImmutableMap<KeyT, ValT>::Factory &F) 00300 : Root(X.getRootWithoutRetain()), 00301 Factory(F.getTreeFactory()) { 00302 if (Root) { Root->retain(); } 00303 } 00304 00305 ImmutableMapRef(const ImmutableMapRef &X) 00306 : Root(X.Root), 00307 Factory(X.Factory) { 00308 if (Root) { Root->retain(); } 00309 } 00310 00311 ImmutableMapRef &operator=(const ImmutableMapRef &X) { 00312 if (Root != X.Root) { 00313 if (X.Root) 00314 X.Root->retain(); 00315 00316 if (Root) 00317 Root->release(); 00318 00319 Root = X.Root; 00320 Factory = X.Factory; 00321 } 00322 return *this; 00323 } 00324 00325 ~ImmutableMapRef() { 00326 if (Root) 00327 Root->release(); 00328 } 00329 00330 static inline ImmutableMapRef getEmptyMap(FactoryTy *F) { 00331 return ImmutableMapRef(0, F); 00332 } 00333 00334 void manualRetain() { 00335 if (Root) Root->retain(); 00336 } 00337 00338 void manualRelease() { 00339 if (Root) Root->release(); 00340 } 00341 00342 ImmutableMapRef add(key_type_ref K, data_type_ref D) const { 00343 TreeTy *NewT = Factory->add(Root, std::pair<key_type, data_type>(K, D)); 00344 return ImmutableMapRef(NewT, Factory); 00345 } 00346 00347 ImmutableMapRef remove(key_type_ref K) const { 00348 TreeTy *NewT = Factory->remove(Root, K); 00349 return ImmutableMapRef(NewT, Factory); 00350 } 00351 00352 bool contains(key_type_ref K) const { 00353 return Root ? Root->contains(K) : false; 00354 } 00355 00356 ImmutableMap<KeyT, ValT> asImmutableMap() const { 00357 return ImmutableMap<KeyT, ValT>(Factory->getCanonicalTree(Root)); 00358 } 00359 00360 bool operator==(const ImmutableMapRef &RHS) const { 00361 return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root; 00362 } 00363 00364 bool operator!=(const ImmutableMapRef &RHS) const { 00365 return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root; 00366 } 00367 00368 bool isEmpty() const { return !Root; } 00369 00370 //===--------------------------------------------------===// 00371 // For testing. 00372 //===--------------------------------------------------===// 00373 00374 void verify() const { if (Root) Root->verify(); } 00375 00376 //===--------------------------------------------------===// 00377 // Iterators. 00378 //===--------------------------------------------------===// 00379 00380 class iterator { 00381 typename TreeTy::iterator itr; 00382 00383 iterator() {} 00384 iterator(TreeTy* t) : itr(t) {} 00385 friend class ImmutableMapRef; 00386 00387 public: 00388 value_type_ref operator*() const { return itr->getValue(); } 00389 value_type* operator->() const { return &itr->getValue(); } 00390 00391 key_type_ref getKey() const { return itr->getValue().first; } 00392 data_type_ref getData() const { return itr->getValue().second; } 00393 00394 00395 iterator& operator++() { ++itr; return *this; } 00396 iterator operator++(int) { iterator tmp(*this); ++itr; return tmp; } 00397 iterator& operator--() { --itr; return *this; } 00398 iterator operator--(int) { iterator tmp(*this); --itr; return tmp; } 00399 bool operator==(const iterator& RHS) const { return RHS.itr == itr; } 00400 bool operator!=(const iterator& RHS) const { return RHS.itr != itr; } 00401 }; 00402 00403 iterator begin() const { return iterator(Root); } 00404 iterator end() const { return iterator(); } 00405 00406 data_type* lookup(key_type_ref K) const { 00407 if (Root) { 00408 TreeTy* T = Root->find(K); 00409 if (T) return &T->getValue().second; 00410 } 00411 00412 return 0; 00413 } 00414 00415 /// getMaxElement - Returns the <key,value> pair in the ImmutableMap for 00416 /// which key is the highest in the ordering of keys in the map. This 00417 /// method returns NULL if the map is empty. 00418 value_type* getMaxElement() const { 00419 return Root ? &(Root->getMaxElement()->getValue()) : 0; 00420 } 00421 00422 //===--------------------------------------------------===// 00423 // Utility methods. 00424 //===--------------------------------------------------===// 00425 00426 unsigned getHeight() const { return Root ? Root->getHeight() : 0; } 00427 00428 static inline void Profile(FoldingSetNodeID& ID, const ImmutableMapRef &M) { 00429 ID.AddPointer(M.Root); 00430 } 00431 00432 inline void Profile(FoldingSetNodeID& ID) const { 00433 return Profile(ID, *this); 00434 } 00435 }; 00436 00437 } // end namespace llvm 00438 00439 #endif