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