Home | History | Annotate | Download | only in ADT
      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_IMMAP_H
     15 #define LLVM_ADT_IMMAP_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 
     33   static inline key_type_ref KeyOfValue(value_type_ref V) {
     34     return V.first;
     35   }
     36 
     37   static inline data_type_ref DataOfValue(value_type_ref V) {
     38     return V.second;
     39   }
     40 
     41   static inline bool isEqual(key_type_ref L, key_type_ref R) {
     42     return ImutContainerInfo<T>::isEqual(L,R);
     43   }
     44   static inline bool isLess(key_type_ref L, key_type_ref R) {
     45     return ImutContainerInfo<T>::isLess(L,R);
     46   }
     47 
     48   static inline bool isDataEqual(data_type_ref L, data_type_ref R) {
     49     return ImutContainerInfo<S>::isEqual(L,R);
     50   }
     51 
     52   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.
     79   explicit ImmutableMap(const TreeTy* R) : Root(const_cast<TreeTy*>(R)) {
     80     if (Root) { Root->retain(); }
     81   }
     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   }
     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)
    103       : Canonicalize(canonicalize) {}
    104 
    105     Factory(BumpPtrAllocator& Alloc, bool canonicalize = true)
    106       : F(Alloc), Canonicalize(canonicalize) {}
    107 
    108     ImmutableMap getEmptyMap() { return ImmutableMap(F.getEmptyTree()); }
    109 
    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 
    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 
    120     typename TreeTy::Factory *getTreeFactory() const {
    121       return const_cast<typename TreeTy::Factory *>(&F);
    122     }
    123 
    124   private:
    125     Factory(const Factory& RHS); // DO NOT IMPLEMENT
    126     void operator=(const Factory& RHS); // DO NOT IMPLEMENT
    127   };
    128 
    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 
    141   TreeTy *getRoot() const {
    142     if (Root) { Root->retain(); }
    143     return Root;
    144   }
    145 
    146   TreeTy *getRootWithoutRetain() const {
    147     return Root;
    148   }
    149 
    150   void manualRetain() {
    151     if (Root) Root->retain();
    152   }
    153 
    154   void manualRelease() {
    155     if (Root) Root->release();
    156   }
    157 
    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;
    168     void operator()(value_type_ref V) { C(V.first,V.second); }
    169   };
    170 
    171   template <typename Callback>
    172   struct CBWrapperRef {
    173     Callback &C;
    174     CBWrapperRef(Callback& c) : C(c) {}
    175 
    176     void operator()(value_type_ref V) { C(V.first,V.second); }
    177   };
    178 
    179 public:
    180   template <typename Callback>
    181   void foreach(Callback& C) {
    182     if (Root) {
    183       CBWrapperRef<Callback> CB(C);
    184       Root->foreach(CB);
    185     }
    186   }
    187 
    188   template <typename Callback>
    189   void foreach() {
    190     if (Root) {
    191       CBWrapper<Callback> CB;
    192       Root->foreach(CB);
    193     }
    194   }
    195 
    196   //===--------------------------------------------------===//
    197   // For testing.
    198   //===--------------------------------------------------===//
    199 
    200   void verify() const { if (Root) Root->verify(); }
    201 
    202   //===--------------------------------------------------===//
    203   // Iterators.
    204   //===--------------------------------------------------===//
    205 
    206   class iterator {
    207     typename TreeTy::iterator itr;
    208 
    209     iterator() {}
    210     iterator(TreeTy* t) : itr(t) {}
    211     friend class ImmutableMap;
    212 
    213   public:
    214     value_type_ref operator*() const { return itr->getValue(); }
    215     value_type*    operator->() const { return &itr->getValue(); }
    216 
    217     key_type_ref getKey() const { return itr->getValue().first; }
    218     data_type_ref getData() const { return itr->getValue().second; }
    219 
    220 
    221     iterator& operator++() { ++itr; return *this; }
    222     iterator  operator++(int) { iterator tmp(*this); ++itr; return tmp; }
    223     iterator& operator--() { --itr; return *this; }
    224     iterator  operator--(int) { iterator tmp(*this); --itr; return tmp; }
    225     bool operator==(const iterator& RHS) const { return RHS.itr == itr; }
    226     bool operator!=(const iterator& RHS) const { return RHS.itr != itr; }
    227   };
    228 
    229   iterator begin() const { return iterator(Root); }
    230   iterator end() const { return iterator(); }
    231 
    232   data_type* lookup(key_type_ref K) const {
    233     if (Root) {
    234       TreeTy* T = Root->find(K);
    235       if (T) return &T->getValue().second;
    236     }
    237 
    238     return 0;
    239   }
    240 
    241   /// getMaxElement - Returns the <key,value> pair in the ImmutableMap for
    242   ///  which key is the highest in the ordering of keys in the map.  This
    243   ///  method returns NULL if the map is empty.
    244   value_type* getMaxElement() const {
    245     return Root ? &(Root->getMaxElement()->getValue()) : 0;
    246   }
    247 
    248   //===--------------------------------------------------===//
    249   // Utility methods.
    250   //===--------------------------------------------------===//
    251 
    252   unsigned getHeight() const { return Root ? Root->getHeight() : 0; }
    253 
    254   static inline void Profile(FoldingSetNodeID& ID, const ImmutableMap& M) {
    255     ID.AddPointer(M.Root);
    256   }
    257 
    258   inline void Profile(FoldingSetNodeID& ID) const {
    259     return Profile(ID,*this);
    260   }
    261 };
    262 
    263 // NOTE: This will possibly become the new implementation of ImmutableMap some day.
    264 template <typename KeyT, typename ValT,
    265 typename ValInfo = ImutKeyValueInfo<KeyT,ValT> >
    266 class ImmutableMapRef {
    267 public:
    268   typedef typename ValInfo::value_type      value_type;
    269   typedef typename ValInfo::value_type_ref  value_type_ref;
    270   typedef typename ValInfo::key_type        key_type;
    271   typedef typename ValInfo::key_type_ref    key_type_ref;
    272   typedef typename ValInfo::data_type       data_type;
    273   typedef typename ValInfo::data_type_ref   data_type_ref;
    274   typedef ImutAVLTree<ValInfo>              TreeTy;
    275   typedef typename TreeTy::Factory          FactoryTy;
    276 
    277 protected:
    278   TreeTy *Root;
    279   FactoryTy *Factory;
    280 
    281 public:
    282   /// Constructs a map from a pointer to a tree root.  In general one
    283   /// should use a Factory object to create maps instead of directly
    284   /// invoking the constructor, but there are cases where make this
    285   /// constructor public is useful.
    286   explicit ImmutableMapRef(const TreeTy* R, FactoryTy *F)
    287     : Root(const_cast<TreeTy*>(R)),
    288       Factory(F) {
    289     if (Root) { Root->retain(); }
    290   }
    291 
    292   ImmutableMapRef(const ImmutableMapRef &X)
    293     : Root(X.Root),
    294       Factory(X.Factory) {
    295     if (Root) { Root->retain(); }
    296   }
    297 
    298   ImmutableMapRef &operator=(const ImmutableMapRef &X) {
    299     if (Root != X.Root) {
    300       if (X.Root)
    301         X.Root->retain();
    302 
    303       if (Root)
    304         Root->release();
    305 
    306       Root = X.Root;
    307       Factory = X.Factory;
    308     }
    309     return *this;
    310   }
    311 
    312   ~ImmutableMapRef() {
    313     if (Root)
    314       Root->release();
    315   }
    316 
    317   static inline ImmutableMapRef getEmptyMap(FactoryTy *F) {
    318     return ImmutableMapRef(0, F);
    319   }
    320 
    321   ImmutableMapRef add(key_type_ref K, data_type_ref D) {
    322     TreeTy *NewT = Factory->add(Root, std::pair<key_type, data_type>(K, D));
    323     return ImmutableMapRef(NewT, Factory);
    324   }
    325 
    326   ImmutableMapRef remove(key_type_ref K) {
    327     TreeTy *NewT = Factory->remove(Root, K);
    328     return ImmutableMapRef(NewT, Factory);
    329   }
    330 
    331   bool contains(key_type_ref K) const {
    332     return Root ? Root->contains(K) : false;
    333   }
    334 
    335   ImmutableMap<KeyT, ValT> asImmutableMap() const {
    336     return ImmutableMap<KeyT, ValT>(Factory->getCanonicalTree(Root));
    337   }
    338 
    339   bool operator==(const ImmutableMapRef &RHS) const {
    340     return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root;
    341   }
    342 
    343   bool operator!=(const ImmutableMapRef &RHS) const {
    344     return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root;
    345   }
    346 
    347   bool isEmpty() const { return !Root; }
    348 
    349   //===--------------------------------------------------===//
    350   // For testing.
    351   //===--------------------------------------------------===//
    352 
    353   void verify() const { if (Root) Root->verify(); }
    354 
    355   //===--------------------------------------------------===//
    356   // Iterators.
    357   //===--------------------------------------------------===//
    358 
    359   class iterator {
    360     typename TreeTy::iterator itr;
    361 
    362     iterator() {}
    363     iterator(TreeTy* t) : itr(t) {}
    364     friend class ImmutableMapRef;
    365 
    366   public:
    367     value_type_ref operator*() const { return itr->getValue(); }
    368     value_type*    operator->() const { return &itr->getValue(); }
    369 
    370     key_type_ref getKey() const { return itr->getValue().first; }
    371     data_type_ref getData() const { return itr->getValue().second; }
    372 
    373 
    374     iterator& operator++() { ++itr; return *this; }
    375     iterator  operator++(int) { iterator tmp(*this); ++itr; return tmp; }
    376     iterator& operator--() { --itr; return *this; }
    377     iterator  operator--(int) { iterator tmp(*this); --itr; return tmp; }
    378     bool operator==(const iterator& RHS) const { return RHS.itr == itr; }
    379     bool operator!=(const iterator& RHS) const { return RHS.itr != itr; }
    380   };
    381 
    382   iterator begin() const { return iterator(Root); }
    383   iterator end() const { return iterator(); }
    384 
    385   data_type* lookup(key_type_ref K) const {
    386     if (Root) {
    387       TreeTy* T = Root->find(K);
    388       if (T) return &T->getValue().second;
    389     }
    390 
    391     return 0;
    392   }
    393 
    394   /// getMaxElement - Returns the <key,value> pair in the ImmutableMap for
    395   ///  which key is the highest in the ordering of keys in the map.  This
    396   ///  method returns NULL if the map is empty.
    397   value_type* getMaxElement() const {
    398     return Root ? &(Root->getMaxElement()->getValue()) : 0;
    399   }
    400 
    401   //===--------------------------------------------------===//
    402   // Utility methods.
    403   //===--------------------------------------------------===//
    404 
    405   unsigned getHeight() const { return Root ? Root->getHeight() : 0; }
    406 
    407   static inline void Profile(FoldingSetNodeID& ID, const ImmutableMapRef &M) {
    408     ID.AddPointer(M.Root);
    409   }
    410 
    411   inline void Profile(FoldingSetNodeID& ID) const {
    412     return Profile(ID, *this);
    413   }
    414 };
    415 
    416 } // end namespace llvm
    417 
    418 #endif
    419