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 typename ImmutableMap<KeyT,ValT,ValInfo>::value_type value_type; 00215 typedef typename ImmutableMap<KeyT,ValT,ValInfo>::value_type_ref reference; 00216 typedef typename iterator::value_type *pointer; 00217 typedef std::bidirectional_iterator_tag iterator_category; 00218 00219 typename iterator::reference operator*() const { return itr->getValue(); } 00220 typename iterator::pointer operator->() const { return &itr->getValue(); } 00221 00222 key_type_ref getKey() const { return itr->getValue().first; } 00223 data_type_ref getData() const { return itr->getValue().second; } 00224 00225 iterator& operator++() { ++itr; return *this; } 00226 iterator operator++(int) { iterator tmp(*this); ++itr; return tmp; } 00227 iterator& operator--() { --itr; return *this; } 00228 iterator operator--(int) { iterator tmp(*this); --itr; return tmp; } 00229 00230 bool operator==(const iterator& RHS) const { return RHS.itr == itr; } 00231 bool operator!=(const iterator& RHS) const { return RHS.itr != itr; } 00232 }; 00233 00234 iterator begin() const { return iterator(Root); } 00235 iterator end() const { return iterator(); } 00236 00237 data_type* lookup(key_type_ref K) const { 00238 if (Root) { 00239 TreeTy* T = Root->find(K); 00240 if (T) return &T->getValue().second; 00241 } 00242 00243 return 0; 00244 } 00245 00246 /// getMaxElement - Returns the <key,value> pair in the ImmutableMap for 00247 /// which key is the highest in the ordering of keys in the map. This 00248 /// method returns NULL if the map is empty. 00249 value_type* getMaxElement() const { 00250 return Root ? &(Root->getMaxElement()->getValue()) : 0; 00251 } 00252 00253 //===--------------------------------------------------===// 00254 // Utility methods. 00255 //===--------------------------------------------------===// 00256 00257 unsigned getHeight() const { return Root ? Root->getHeight() : 0; } 00258 00259 static inline void Profile(FoldingSetNodeID& ID, const ImmutableMap& M) { 00260 ID.AddPointer(M.Root); 00261 } 00262 00263 inline void Profile(FoldingSetNodeID& ID) const { 00264 return Profile(ID,*this); 00265 } 00266 }; 00267 00268 // NOTE: This will possibly become the new implementation of ImmutableMap some day. 00269 template <typename KeyT, typename ValT, 00270 typename ValInfo = ImutKeyValueInfo<KeyT,ValT> > 00271 class ImmutableMapRef { 00272 public: 00273 typedef typename ValInfo::value_type value_type; 00274 typedef typename ValInfo::value_type_ref value_type_ref; 00275 typedef typename ValInfo::key_type key_type; 00276 typedef typename ValInfo::key_type_ref key_type_ref; 00277 typedef typename ValInfo::data_type data_type; 00278 typedef typename ValInfo::data_type_ref data_type_ref; 00279 typedef ImutAVLTree<ValInfo> TreeTy; 00280 typedef typename TreeTy::Factory FactoryTy; 00281 00282 protected: 00283 TreeTy *Root; 00284 FactoryTy *Factory; 00285 00286 public: 00287 /// Constructs a map from a pointer to a tree root. In general one 00288 /// should use a Factory object to create maps instead of directly 00289 /// invoking the constructor, but there are cases where make this 00290 /// constructor public is useful. 00291 explicit ImmutableMapRef(const TreeTy* R, FactoryTy *F) 00292 : Root(const_cast<TreeTy*>(R)), 00293 Factory(F) { 00294 if (Root) { Root->retain(); } 00295 } 00296 00297 explicit ImmutableMapRef(const ImmutableMap<KeyT, ValT> &X, 00298 typename ImmutableMap<KeyT, ValT>::Factory &F) 00299 : Root(X.getRootWithoutRetain()), 00300 Factory(F.getTreeFactory()) { 00301 if (Root) { Root->retain(); } 00302 } 00303 00304 ImmutableMapRef(const ImmutableMapRef &X) 00305 : Root(X.Root), 00306 Factory(X.Factory) { 00307 if (Root) { Root->retain(); } 00308 } 00309 00310 ImmutableMapRef &operator=(const ImmutableMapRef &X) { 00311 if (Root != X.Root) { 00312 if (X.Root) 00313 X.Root->retain(); 00314 00315 if (Root) 00316 Root->release(); 00317 00318 Root = X.Root; 00319 Factory = X.Factory; 00320 } 00321 return *this; 00322 } 00323 00324 ~ImmutableMapRef() { 00325 if (Root) 00326 Root->release(); 00327 } 00328 00329 static inline ImmutableMapRef getEmptyMap(FactoryTy *F) { 00330 return ImmutableMapRef(0, F); 00331 } 00332 00333 void manualRetain() { 00334 if (Root) Root->retain(); 00335 } 00336 00337 void manualRelease() { 00338 if (Root) Root->release(); 00339 } 00340 00341 ImmutableMapRef add(key_type_ref K, data_type_ref D) const { 00342 TreeTy *NewT = Factory->add(Root, std::pair<key_type, data_type>(K, D)); 00343 return ImmutableMapRef(NewT, Factory); 00344 } 00345 00346 ImmutableMapRef remove(key_type_ref K) const { 00347 TreeTy *NewT = Factory->remove(Root, K); 00348 return ImmutableMapRef(NewT, Factory); 00349 } 00350 00351 bool contains(key_type_ref K) const { 00352 return Root ? Root->contains(K) : false; 00353 } 00354 00355 ImmutableMap<KeyT, ValT> asImmutableMap() const { 00356 return ImmutableMap<KeyT, ValT>(Factory->getCanonicalTree(Root)); 00357 } 00358 00359 bool operator==(const ImmutableMapRef &RHS) const { 00360 return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root; 00361 } 00362 00363 bool operator!=(const ImmutableMapRef &RHS) const { 00364 return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root; 00365 } 00366 00367 bool isEmpty() const { return !Root; } 00368 00369 //===--------------------------------------------------===// 00370 // For testing. 00371 //===--------------------------------------------------===// 00372 00373 void verify() const { if (Root) Root->verify(); } 00374 00375 //===--------------------------------------------------===// 00376 // Iterators. 00377 //===--------------------------------------------------===// 00378 00379 class iterator { 00380 typename TreeTy::iterator itr; 00381 00382 iterator() {} 00383 iterator(TreeTy* t) : itr(t) {} 00384 friend class ImmutableMapRef; 00385 00386 public: 00387 value_type_ref operator*() const { return itr->getValue(); } 00388 value_type* operator->() const { return &itr->getValue(); } 00389 00390 key_type_ref getKey() const { return itr->getValue().first; } 00391 data_type_ref getData() const { return itr->getValue().second; } 00392 00393 00394 iterator& operator++() { ++itr; return *this; } 00395 iterator operator++(int) { iterator tmp(*this); ++itr; return tmp; } 00396 iterator& operator--() { --itr; return *this; } 00397 iterator operator--(int) { iterator tmp(*this); --itr; return tmp; } 00398 bool operator==(const iterator& RHS) const { return RHS.itr == itr; } 00399 bool operator!=(const iterator& RHS) const { return RHS.itr != itr; } 00400 }; 00401 00402 iterator begin() const { return iterator(Root); } 00403 iterator end() const { return iterator(); } 00404 00405 data_type* lookup(key_type_ref K) const { 00406 if (Root) { 00407 TreeTy* T = Root->find(K); 00408 if (T) return &T->getValue().second; 00409 } 00410 00411 return 0; 00412 } 00413 00414 /// getMaxElement - Returns the <key,value> pair in the ImmutableMap for 00415 /// which key is the highest in the ordering of keys in the map. This 00416 /// method returns NULL if the map is empty. 00417 value_type* getMaxElement() const { 00418 return Root ? &(Root->getMaxElement()->getValue()) : 0; 00419 } 00420 00421 //===--------------------------------------------------===// 00422 // Utility methods. 00423 //===--------------------------------------------------===// 00424 00425 unsigned getHeight() const { return Root ? Root->getHeight() : 0; } 00426 00427 static inline void Profile(FoldingSetNodeID& ID, const ImmutableMapRef &M) { 00428 ID.AddPointer(M.Root); 00429 } 00430 00431 inline void Profile(FoldingSetNodeID& ID) const { 00432 return Profile(ID, *this); 00433 } 00434 }; 00435 00436 } // end namespace llvm 00437 00438 #endif