Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:06

0001 //===--- ImmutableMap.h - Immutable (functional) map interface --*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 ///
0009 /// \file
0010 /// This file defines the ImmutableMap class.
0011 ///
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_ADT_IMMUTABLEMAP_H
0015 #define LLVM_ADT_IMMUTABLEMAP_H
0016 
0017 #include "llvm/ADT/FoldingSet.h"
0018 #include "llvm/ADT/ImmutableSet.h"
0019 #include "llvm/Support/Allocator.h"
0020 #include <utility>
0021 
0022 namespace llvm {
0023 
0024 /// ImutKeyValueInfo -Traits class used by ImmutableMap.  While both the first
0025 /// and second elements in a pair are used to generate profile information,
0026 /// only the first element (the key) is used by isEqual and isLess.
0027 template <typename T, typename S>
0028 struct ImutKeyValueInfo {
0029   using value_type = const std::pair<T,S>;
0030   using value_type_ref = const value_type&;
0031   using key_type = const T;
0032   using key_type_ref = const T&;
0033   using data_type = const S;
0034   using data_type_ref = const S&;
0035 
0036   static inline key_type_ref KeyOfValue(value_type_ref V) {
0037     return V.first;
0038   }
0039 
0040   static inline data_type_ref DataOfValue(value_type_ref V) {
0041     return V.second;
0042   }
0043 
0044   static inline bool isEqual(key_type_ref L, key_type_ref R) {
0045     return ImutContainerInfo<T>::isEqual(L,R);
0046   }
0047   static inline bool isLess(key_type_ref L, key_type_ref R) {
0048     return ImutContainerInfo<T>::isLess(L,R);
0049   }
0050 
0051   static inline bool isDataEqual(data_type_ref L, data_type_ref R) {
0052     return ImutContainerInfo<S>::isEqual(L,R);
0053   }
0054 
0055   static inline void Profile(FoldingSetNodeID& ID, value_type_ref V) {
0056     ImutContainerInfo<T>::Profile(ID, V.first);
0057     ImutContainerInfo<S>::Profile(ID, V.second);
0058   }
0059 };
0060 
0061 template <typename KeyT, typename ValT,
0062           typename ValInfo = ImutKeyValueInfo<KeyT,ValT>>
0063 class ImmutableMap {
0064 public:
0065   using value_type = typename ValInfo::value_type;
0066   using value_type_ref = typename ValInfo::value_type_ref;
0067   using key_type = typename ValInfo::key_type;
0068   using key_type_ref = typename ValInfo::key_type_ref;
0069   using data_type = typename ValInfo::data_type;
0070   using data_type_ref = typename ValInfo::data_type_ref;
0071   using TreeTy = ImutAVLTree<ValInfo>;
0072 
0073 protected:
0074   IntrusiveRefCntPtr<TreeTy> Root;
0075 
0076 public:
0077   /// Constructs a map from a pointer to a tree root.  In general one
0078   /// should use a Factory object to create maps instead of directly
0079   /// invoking the constructor, but there are cases where make this
0080   /// constructor public is useful.
0081   explicit ImmutableMap(const TreeTy *R) : Root(const_cast<TreeTy *>(R)) {}
0082 
0083   class Factory {
0084     typename TreeTy::Factory F;
0085     const bool Canonicalize;
0086 
0087   public:
0088     Factory(bool canonicalize = true) : Canonicalize(canonicalize) {}
0089 
0090     Factory(BumpPtrAllocator &Alloc, bool canonicalize = true)
0091         : F(Alloc), Canonicalize(canonicalize) {}
0092 
0093     Factory(const Factory &) = delete;
0094     Factory &operator=(const Factory &) = delete;
0095 
0096     ImmutableMap getEmptyMap() { return ImmutableMap(F.getEmptyTree()); }
0097 
0098     [[nodiscard]] ImmutableMap add(ImmutableMap Old, key_type_ref K,
0099                                    data_type_ref D) {
0100       TreeTy *T = F.add(Old.Root.get(), std::pair<key_type, data_type>(K, D));
0101       return ImmutableMap(Canonicalize ? F.getCanonicalTree(T): T);
0102     }
0103 
0104     [[nodiscard]] ImmutableMap remove(ImmutableMap Old, key_type_ref K) {
0105       TreeTy *T = F.remove(Old.Root.get(), K);
0106       return ImmutableMap(Canonicalize ? F.getCanonicalTree(T): T);
0107     }
0108 
0109     typename TreeTy::Factory *getTreeFactory() const {
0110       return const_cast<typename TreeTy::Factory *>(&F);
0111     }
0112   };
0113 
0114   bool contains(key_type_ref K) const {
0115     return Root ? Root->contains(K) : false;
0116   }
0117 
0118   bool operator==(const ImmutableMap &RHS) const {
0119     return Root && RHS.Root ? Root->isEqual(*RHS.Root.get()) : Root == RHS.Root;
0120   }
0121 
0122   bool operator!=(const ImmutableMap &RHS) const {
0123     return Root && RHS.Root ? Root->isNotEqual(*RHS.Root.get())
0124                             : Root != RHS.Root;
0125   }
0126 
0127   TreeTy *getRoot() const {
0128     if (Root) { Root->retain(); }
0129     return Root.get();
0130   }
0131 
0132   TreeTy *getRootWithoutRetain() const { return Root.get(); }
0133 
0134   void manualRetain() {
0135     if (Root) Root->retain();
0136   }
0137 
0138   void manualRelease() {
0139     if (Root) Root->release();
0140   }
0141 
0142   bool isEmpty() const { return !Root; }
0143 
0144 public:
0145   //===--------------------------------------------------===//
0146   // For testing.
0147   //===--------------------------------------------------===//
0148 
0149   void verify() const { if (Root) Root->verify(); }
0150 
0151   //===--------------------------------------------------===//
0152   // Iterators.
0153   //===--------------------------------------------------===//
0154 
0155   class iterator : public ImutAVLValueIterator<ImmutableMap> {
0156     friend class ImmutableMap;
0157 
0158     iterator() = default;
0159     explicit iterator(TreeTy *Tree) : iterator::ImutAVLValueIterator(Tree) {}
0160 
0161   public:
0162     key_type_ref getKey() const { return (*this)->first; }
0163     data_type_ref getData() const { return (*this)->second; }
0164   };
0165 
0166   iterator begin() const { return iterator(Root.get()); }
0167   iterator end() const { return iterator(); }
0168 
0169   data_type* lookup(key_type_ref K) const {
0170     if (Root) {
0171       TreeTy* T = Root->find(K);
0172       if (T) return &T->getValue().second;
0173     }
0174 
0175     return nullptr;
0176   }
0177 
0178   /// getMaxElement - Returns the <key,value> pair in the ImmutableMap for
0179   ///  which key is the highest in the ordering of keys in the map.  This
0180   ///  method returns NULL if the map is empty.
0181   value_type* getMaxElement() const {
0182     return Root ? &(Root->getMaxElement()->getValue()) : nullptr;
0183   }
0184 
0185   //===--------------------------------------------------===//
0186   // Utility methods.
0187   //===--------------------------------------------------===//
0188 
0189   unsigned getHeight() const { return Root ? Root->getHeight() : 0; }
0190 
0191   static inline void Profile(FoldingSetNodeID& ID, const ImmutableMap& M) {
0192     ID.AddPointer(M.Root.get());
0193   }
0194 
0195   inline void Profile(FoldingSetNodeID& ID) const {
0196     return Profile(ID,*this);
0197   }
0198 };
0199 
0200 // NOTE: This will possibly become the new implementation of ImmutableMap some day.
0201 template <typename KeyT, typename ValT,
0202 typename ValInfo = ImutKeyValueInfo<KeyT,ValT>>
0203 class ImmutableMapRef {
0204 public:
0205   using value_type = typename ValInfo::value_type;
0206   using value_type_ref = typename ValInfo::value_type_ref;
0207   using key_type = typename ValInfo::key_type;
0208   using key_type_ref = typename ValInfo::key_type_ref;
0209   using data_type = typename ValInfo::data_type;
0210   using data_type_ref = typename ValInfo::data_type_ref;
0211   using TreeTy = ImutAVLTree<ValInfo>;
0212   using FactoryTy = typename TreeTy::Factory;
0213 
0214 protected:
0215   IntrusiveRefCntPtr<TreeTy> Root;
0216   FactoryTy *Factory;
0217 
0218 public:
0219   /// Constructs a map from a pointer to a tree root.  In general one
0220   /// should use a Factory object to create maps instead of directly
0221   /// invoking the constructor, but there are cases where make this
0222   /// constructor public is useful.
0223   ImmutableMapRef(const TreeTy *R, FactoryTy *F)
0224       : Root(const_cast<TreeTy *>(R)), Factory(F) {}
0225 
0226   ImmutableMapRef(const ImmutableMap<KeyT, ValT> &X,
0227                   typename ImmutableMap<KeyT, ValT>::Factory &F)
0228       : Root(X.getRootWithoutRetain()), Factory(F.getTreeFactory()) {}
0229 
0230   static inline ImmutableMapRef getEmptyMap(FactoryTy *F) {
0231     return ImmutableMapRef(nullptr, F);
0232   }
0233 
0234   void manualRetain() {
0235     if (Root) Root->retain();
0236   }
0237 
0238   void manualRelease() {
0239     if (Root) Root->release();
0240   }
0241 
0242   ImmutableMapRef add(key_type_ref K, data_type_ref D) const {
0243     TreeTy *NewT =
0244         Factory->add(Root.get(), std::pair<key_type, data_type>(K, D));
0245     return ImmutableMapRef(NewT, Factory);
0246   }
0247 
0248   ImmutableMapRef remove(key_type_ref K) const {
0249     TreeTy *NewT = Factory->remove(Root.get(), K);
0250     return ImmutableMapRef(NewT, Factory);
0251   }
0252 
0253   bool contains(key_type_ref K) const {
0254     return Root ? Root->contains(K) : false;
0255   }
0256 
0257   ImmutableMap<KeyT, ValT> asImmutableMap() const {
0258     return ImmutableMap<KeyT, ValT>(Factory->getCanonicalTree(Root.get()));
0259   }
0260 
0261   bool operator==(const ImmutableMapRef &RHS) const {
0262     return Root && RHS.Root ? Root->isEqual(*RHS.Root.get()) : Root == RHS.Root;
0263   }
0264 
0265   bool operator!=(const ImmutableMapRef &RHS) const {
0266     return Root && RHS.Root ? Root->isNotEqual(*RHS.Root.get())
0267                             : Root != RHS.Root;
0268   }
0269 
0270   bool isEmpty() const { return !Root; }
0271 
0272   //===--------------------------------------------------===//
0273   // For testing.
0274   //===--------------------------------------------------===//
0275 
0276   void verify() const {
0277     if (Root)
0278       Root->verify();
0279   }
0280 
0281   //===--------------------------------------------------===//
0282   // Iterators.
0283   //===--------------------------------------------------===//
0284 
0285   class iterator : public ImutAVLValueIterator<ImmutableMapRef> {
0286     friend class ImmutableMapRef;
0287 
0288     iterator() = default;
0289     explicit iterator(TreeTy *Tree) : iterator::ImutAVLValueIterator(Tree) {}
0290 
0291   public:
0292     key_type_ref getKey() const { return (*this)->first; }
0293     data_type_ref getData() const { return (*this)->second; }
0294   };
0295 
0296   iterator begin() const { return iterator(Root.get()); }
0297   iterator end() const { return iterator(); }
0298 
0299   data_type *lookup(key_type_ref K) const {
0300     if (Root) {
0301       TreeTy* T = Root->find(K);
0302       if (T) return &T->getValue().second;
0303     }
0304 
0305     return nullptr;
0306   }
0307 
0308   /// getMaxElement - Returns the <key,value> pair in the ImmutableMap for
0309   ///  which key is the highest in the ordering of keys in the map.  This
0310   ///  method returns NULL if the map is empty.
0311   value_type* getMaxElement() const {
0312     return Root ? &(Root->getMaxElement()->getValue()) : nullptr;
0313   }
0314 
0315   //===--------------------------------------------------===//
0316   // Utility methods.
0317   //===--------------------------------------------------===//
0318 
0319   unsigned getHeight() const { return Root ? Root->getHeight() : 0; }
0320 
0321   static inline void Profile(FoldingSetNodeID &ID, const ImmutableMapRef &M) {
0322     ID.AddPointer(M.Root.get());
0323   }
0324 
0325   inline void Profile(FoldingSetNodeID &ID) const { return Profile(ID, *this); }
0326 };
0327 
0328 } // end namespace llvm
0329 
0330 #endif // LLVM_ADT_IMMUTABLEMAP_H