1 //===--- ImmutableMap.h - Immutable (functional) map interface --*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines the ImmutableMap class. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_ADT_IMMUTABLEMAP_H 15 #define LLVM_ADT_IMMUTABLEMAP_H 16 17 #include "llvm/ADT/ImmutableSet.h" 18 19 namespace llvm { 20 21 /// ImutKeyValueInfo -Traits class used by ImmutableMap. While both the first 22 /// and second elements in a pair are used to generate profile information, 23 /// only the first element (the key) is used by isEqual and isLess. 24 template <typename T, typename S> 25 struct ImutKeyValueInfo { 26 typedef const std::pair<T,S> value_type; 27 typedef const value_type& value_type_ref; 28 typedef const T key_type; 29 typedef const T& key_type_ref; 30 typedef const S data_type; 31 typedef const S& data_type_ref; 32 KeyOfValueImutKeyValueInfo33 static inline key_type_ref KeyOfValue(value_type_ref V) { 34 return V.first; 35 } 36 DataOfValueImutKeyValueInfo37 static inline data_type_ref DataOfValue(value_type_ref V) { 38 return V.second; 39 } 40 isEqualImutKeyValueInfo41 static inline bool isEqual(key_type_ref L, key_type_ref R) { 42 return ImutContainerInfo<T>::isEqual(L,R); 43 } isLessImutKeyValueInfo44 static inline bool isLess(key_type_ref L, key_type_ref R) { 45 return ImutContainerInfo<T>::isLess(L,R); 46 } 47 isDataEqualImutKeyValueInfo48 static inline bool isDataEqual(data_type_ref L, data_type_ref R) { 49 return ImutContainerInfo<S>::isEqual(L,R); 50 } 51 ProfileImutKeyValueInfo52 static inline void Profile(FoldingSetNodeID& ID, value_type_ref V) { 53 ImutContainerInfo<T>::Profile(ID, V.first); 54 ImutContainerInfo<S>::Profile(ID, V.second); 55 } 56 }; 57 58 59 template <typename KeyT, typename ValT, 60 typename ValInfo = ImutKeyValueInfo<KeyT,ValT> > 61 class ImmutableMap { 62 public: 63 typedef typename ValInfo::value_type value_type; 64 typedef typename ValInfo::value_type_ref value_type_ref; 65 typedef typename ValInfo::key_type key_type; 66 typedef typename ValInfo::key_type_ref key_type_ref; 67 typedef typename ValInfo::data_type data_type; 68 typedef typename ValInfo::data_type_ref data_type_ref; 69 typedef ImutAVLTree<ValInfo> TreeTy; 70 71 protected: 72 TreeTy* Root; 73 74 public: 75 /// Constructs a map from a pointer to a tree root. In general one 76 /// should use a Factory object to create maps instead of directly 77 /// invoking the constructor, but there are cases where make this 78 /// constructor public is useful. ImmutableMap(const TreeTy * R)79 explicit ImmutableMap(const TreeTy* R) : Root(const_cast<TreeTy*>(R)) { 80 if (Root) { Root->retain(); } 81 } ImmutableMap(const ImmutableMap & X)82 ImmutableMap(const ImmutableMap &X) : Root(X.Root) { 83 if (Root) { Root->retain(); } 84 } 85 ImmutableMap &operator=(const ImmutableMap &X) { 86 if (Root != X.Root) { 87 if (X.Root) { X.Root->retain(); } 88 if (Root) { Root->release(); } 89 Root = X.Root; 90 } 91 return *this; 92 } ~ImmutableMap()93 ~ImmutableMap() { 94 if (Root) { Root->release(); } 95 } 96 97 class Factory { 98 typename TreeTy::Factory F; 99 const bool Canonicalize; 100 101 public: 102 Factory(bool canonicalize = true) Canonicalize(canonicalize)103 : Canonicalize(canonicalize) {} 104 105 Factory(BumpPtrAllocator& Alloc, bool canonicalize = true) F(Alloc)106 : F(Alloc), Canonicalize(canonicalize) {} 107 getEmptyMap()108 ImmutableMap getEmptyMap() { return ImmutableMap(F.getEmptyTree()); } 109 add(ImmutableMap Old,key_type_ref K,data_type_ref D)110 ImmutableMap add(ImmutableMap Old, key_type_ref K, data_type_ref D) { 111 TreeTy *T = F.add(Old.Root, std::pair<key_type,data_type>(K,D)); 112 return ImmutableMap(Canonicalize ? F.getCanonicalTree(T): T); 113 } 114 remove(ImmutableMap Old,key_type_ref K)115 ImmutableMap remove(ImmutableMap Old, key_type_ref K) { 116 TreeTy *T = F.remove(Old.Root,K); 117 return ImmutableMap(Canonicalize ? F.getCanonicalTree(T): T); 118 } 119 getTreeFactory()120 typename TreeTy::Factory *getTreeFactory() const { 121 return const_cast<typename TreeTy::Factory *>(&F); 122 } 123 124 private: 125 Factory(const Factory& RHS) = delete; 126 void operator=(const Factory& RHS) = delete; 127 }; 128 contains(key_type_ref K)129 bool contains(key_type_ref K) const { 130 return Root ? Root->contains(K) : false; 131 } 132 133 bool operator==(const ImmutableMap &RHS) const { 134 return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root; 135 } 136 137 bool operator!=(const ImmutableMap &RHS) const { 138 return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root; 139 } 140 getRoot()141 TreeTy *getRoot() const { 142 if (Root) { Root->retain(); } 143 return Root; 144 } 145 getRootWithoutRetain()146 TreeTy *getRootWithoutRetain() const { 147 return Root; 148 } 149 manualRetain()150 void manualRetain() { 151 if (Root) Root->retain(); 152 } 153 manualRelease()154 void manualRelease() { 155 if (Root) Root->release(); 156 } 157 isEmpty()158 bool isEmpty() const { return !Root; } 159 160 //===--------------------------------------------------===// 161 // Foreach - A limited form of map iteration. 162 //===--------------------------------------------------===// 163 164 private: 165 template <typename Callback> 166 struct CBWrapper { 167 Callback C; operatorCBWrapper168 void operator()(value_type_ref V) { C(V.first,V.second); } 169 }; 170 171 template <typename Callback> 172 struct CBWrapperRef { 173 Callback &C; CBWrapperRefCBWrapperRef174 CBWrapperRef(Callback& c) : C(c) {} 175 operatorCBWrapperRef176 void operator()(value_type_ref V) { C(V.first,V.second); } 177 }; 178 179 public: 180 template <typename Callback> foreach(Callback & C)181 void foreach(Callback& C) { 182 if (Root) { 183 CBWrapperRef<Callback> CB(C); 184 Root->foreach(CB); 185 } 186 } 187 188 template <typename Callback> foreach()189 void foreach() { 190 if (Root) { 191 CBWrapper<Callback> CB; 192 Root->foreach(CB); 193 } 194 } 195 196 //===--------------------------------------------------===// 197 // For testing. 198 //===--------------------------------------------------===// 199 verify()200 void verify() const { if (Root) Root->verify(); } 201 202 //===--------------------------------------------------===// 203 // Iterators. 204 //===--------------------------------------------------===// 205 206 class iterator : public ImutAVLValueIterator<ImmutableMap> { 207 iterator() = default; iterator(TreeTy * Tree)208 explicit iterator(TreeTy *Tree) : iterator::ImutAVLValueIterator(Tree) {} 209 friend class ImmutableMap; 210 211 public: getKey()212 key_type_ref getKey() const { return (*this)->first; } getData()213 data_type_ref getData() const { return (*this)->second; } 214 }; 215 begin()216 iterator begin() const { return iterator(Root); } end()217 iterator end() const { return iterator(); } 218 lookup(key_type_ref K)219 data_type* lookup(key_type_ref K) const { 220 if (Root) { 221 TreeTy* T = Root->find(K); 222 if (T) return &T->getValue().second; 223 } 224 225 return nullptr; 226 } 227 228 /// getMaxElement - Returns the <key,value> pair in the ImmutableMap for 229 /// which key is the highest in the ordering of keys in the map. This 230 /// method returns NULL if the map is empty. getMaxElement()231 value_type* getMaxElement() const { 232 return Root ? &(Root->getMaxElement()->getValue()) : nullptr; 233 } 234 235 //===--------------------------------------------------===// 236 // Utility methods. 237 //===--------------------------------------------------===// 238 getHeight()239 unsigned getHeight() const { return Root ? Root->getHeight() : 0; } 240 Profile(FoldingSetNodeID & ID,const ImmutableMap & M)241 static inline void Profile(FoldingSetNodeID& ID, const ImmutableMap& M) { 242 ID.AddPointer(M.Root); 243 } 244 Profile(FoldingSetNodeID & ID)245 inline void Profile(FoldingSetNodeID& ID) const { 246 return Profile(ID,*this); 247 } 248 }; 249 250 // NOTE: This will possibly become the new implementation of ImmutableMap some day. 251 template <typename KeyT, typename ValT, 252 typename ValInfo = ImutKeyValueInfo<KeyT,ValT> > 253 class ImmutableMapRef { 254 public: 255 typedef typename ValInfo::value_type value_type; 256 typedef typename ValInfo::value_type_ref value_type_ref; 257 typedef typename ValInfo::key_type key_type; 258 typedef typename ValInfo::key_type_ref key_type_ref; 259 typedef typename ValInfo::data_type data_type; 260 typedef typename ValInfo::data_type_ref data_type_ref; 261 typedef ImutAVLTree<ValInfo> TreeTy; 262 typedef typename TreeTy::Factory FactoryTy; 263 264 protected: 265 TreeTy *Root; 266 FactoryTy *Factory; 267 268 public: 269 /// Constructs a map from a pointer to a tree root. In general one 270 /// should use a Factory object to create maps instead of directly 271 /// invoking the constructor, but there are cases where make this 272 /// constructor public is useful. ImmutableMapRef(const TreeTy * R,FactoryTy * F)273 explicit ImmutableMapRef(const TreeTy* R, FactoryTy *F) 274 : Root(const_cast<TreeTy*>(R)), 275 Factory(F) { 276 if (Root) { Root->retain(); } 277 } 278 ImmutableMapRef(const ImmutableMap<KeyT,ValT> & X,typename ImmutableMap<KeyT,ValT>::Factory & F)279 explicit ImmutableMapRef(const ImmutableMap<KeyT, ValT> &X, 280 typename ImmutableMap<KeyT, ValT>::Factory &F) 281 : Root(X.getRootWithoutRetain()), 282 Factory(F.getTreeFactory()) { 283 if (Root) { Root->retain(); } 284 } 285 ImmutableMapRef(const ImmutableMapRef & X)286 ImmutableMapRef(const ImmutableMapRef &X) 287 : Root(X.Root), 288 Factory(X.Factory) { 289 if (Root) { Root->retain(); } 290 } 291 292 ImmutableMapRef &operator=(const ImmutableMapRef &X) { 293 if (Root != X.Root) { 294 if (X.Root) 295 X.Root->retain(); 296 297 if (Root) 298 Root->release(); 299 300 Root = X.Root; 301 Factory = X.Factory; 302 } 303 return *this; 304 } 305 ~ImmutableMapRef()306 ~ImmutableMapRef() { 307 if (Root) 308 Root->release(); 309 } 310 getEmptyMap(FactoryTy * F)311 static inline ImmutableMapRef getEmptyMap(FactoryTy *F) { 312 return ImmutableMapRef(0, F); 313 } 314 manualRetain()315 void manualRetain() { 316 if (Root) Root->retain(); 317 } 318 manualRelease()319 void manualRelease() { 320 if (Root) Root->release(); 321 } 322 add(key_type_ref K,data_type_ref D)323 ImmutableMapRef add(key_type_ref K, data_type_ref D) const { 324 TreeTy *NewT = Factory->add(Root, std::pair<key_type, data_type>(K, D)); 325 return ImmutableMapRef(NewT, Factory); 326 } 327 remove(key_type_ref K)328 ImmutableMapRef remove(key_type_ref K) const { 329 TreeTy *NewT = Factory->remove(Root, K); 330 return ImmutableMapRef(NewT, Factory); 331 } 332 contains(key_type_ref K)333 bool contains(key_type_ref K) const { 334 return Root ? Root->contains(K) : false; 335 } 336 asImmutableMap()337 ImmutableMap<KeyT, ValT> asImmutableMap() const { 338 return ImmutableMap<KeyT, ValT>(Factory->getCanonicalTree(Root)); 339 } 340 341 bool operator==(const ImmutableMapRef &RHS) const { 342 return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root; 343 } 344 345 bool operator!=(const ImmutableMapRef &RHS) const { 346 return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root; 347 } 348 isEmpty()349 bool isEmpty() const { return !Root; } 350 351 //===--------------------------------------------------===// 352 // For testing. 353 //===--------------------------------------------------===// 354 verify()355 void verify() const { if (Root) Root->verify(); } 356 357 //===--------------------------------------------------===// 358 // Iterators. 359 //===--------------------------------------------------===// 360 361 class iterator : public ImutAVLValueIterator<ImmutableMapRef> { 362 iterator() = default; iterator(TreeTy * Tree)363 explicit iterator(TreeTy *Tree) : iterator::ImutAVLValueIterator(Tree) {} 364 friend class ImmutableMapRef; 365 366 public: getKey()367 key_type_ref getKey() const { return (*this)->first; } getData()368 data_type_ref getData() const { return (*this)->second; } 369 }; 370 begin()371 iterator begin() const { return iterator(Root); } end()372 iterator end() const { return iterator(); } 373 lookup(key_type_ref K)374 data_type* lookup(key_type_ref K) const { 375 if (Root) { 376 TreeTy* T = Root->find(K); 377 if (T) return &T->getValue().second; 378 } 379 380 return 0; 381 } 382 383 /// getMaxElement - Returns the <key,value> pair in the ImmutableMap for 384 /// which key is the highest in the ordering of keys in the map. This 385 /// method returns NULL if the map is empty. getMaxElement()386 value_type* getMaxElement() const { 387 return Root ? &(Root->getMaxElement()->getValue()) : 0; 388 } 389 390 //===--------------------------------------------------===// 391 // Utility methods. 392 //===--------------------------------------------------===// 393 getHeight()394 unsigned getHeight() const { return Root ? Root->getHeight() : 0; } 395 Profile(FoldingSetNodeID & ID,const ImmutableMapRef & M)396 static inline void Profile(FoldingSetNodeID& ID, const ImmutableMapRef &M) { 397 ID.AddPointer(M.Root); 398 } 399 Profile(FoldingSetNodeID & ID)400 inline void Profile(FoldingSetNodeID& ID) const { 401 return Profile(ID, *this); 402 } 403 }; 404 405 } // end namespace llvm 406 407 #endif 408