File indexing completed on 2026-05-10 08:43:06
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef LLVM_ADT_IMMUTABLESET_H
0015 #define LLVM_ADT_IMMUTABLESET_H
0016
0017 #include "llvm/ADT/DenseMap.h"
0018 #include "llvm/ADT/FoldingSet.h"
0019 #include "llvm/ADT/IntrusiveRefCntPtr.h"
0020 #include "llvm/ADT/SmallVector.h"
0021 #include "llvm/ADT/iterator.h"
0022 #include "llvm/Support/Allocator.h"
0023 #include "llvm/Support/ErrorHandling.h"
0024 #include <cassert>
0025 #include <cstdint>
0026 #include <functional>
0027 #include <iterator>
0028 #include <new>
0029 #include <vector>
0030
0031 namespace llvm {
0032
0033
0034
0035
0036
0037 template <typename ImutInfo> class ImutAVLFactory;
0038 template <typename ImutInfo> class ImutIntervalAVLFactory;
0039 template <typename ImutInfo> class ImutAVLTreeInOrderIterator;
0040 template <typename ImutInfo> class ImutAVLTreeGenericIterator;
0041
0042 template <typename ImutInfo >
0043 class ImutAVLTree {
0044 public:
0045 using key_type_ref = typename ImutInfo::key_type_ref;
0046 using value_type = typename ImutInfo::value_type;
0047 using value_type_ref = typename ImutInfo::value_type_ref;
0048 using Factory = ImutAVLFactory<ImutInfo>;
0049 using iterator = ImutAVLTreeInOrderIterator<ImutInfo>;
0050
0051 friend class ImutAVLFactory<ImutInfo>;
0052 friend class ImutIntervalAVLFactory<ImutInfo>;
0053 friend class ImutAVLTreeGenericIterator<ImutInfo>;
0054
0055
0056
0057
0058
0059
0060
0061 ImutAVLTree *getLeft() const { return left; }
0062
0063
0064
0065 ImutAVLTree *getRight() const { return right; }
0066
0067
0068
0069 unsigned getHeight() const { return height; }
0070
0071
0072 const value_type& getValue() const { return value; }
0073
0074
0075
0076 ImutAVLTree* find(key_type_ref K) {
0077 ImutAVLTree *T = this;
0078 while (T) {
0079 key_type_ref CurrentKey = ImutInfo::KeyOfValue(T->getValue());
0080 if (ImutInfo::isEqual(K,CurrentKey))
0081 return T;
0082 else if (ImutInfo::isLess(K,CurrentKey))
0083 T = T->getLeft();
0084 else
0085 T = T->getRight();
0086 }
0087 return nullptr;
0088 }
0089
0090
0091
0092 ImutAVLTree* getMaxElement() {
0093 ImutAVLTree *T = this;
0094 ImutAVLTree *Right = T->getRight();
0095 while (Right) { T = Right; Right = T->getRight(); }
0096 return T;
0097 }
0098
0099
0100
0101 unsigned size() const {
0102 unsigned n = 1;
0103 if (const ImutAVLTree* L = getLeft())
0104 n += L->size();
0105 if (const ImutAVLTree* R = getRight())
0106 n += R->size();
0107 return n;
0108 }
0109
0110
0111
0112
0113 iterator begin() const { return iterator(this); }
0114
0115
0116
0117 iterator end() const { return iterator(); }
0118
0119 bool isElementEqual(value_type_ref V) const {
0120
0121 if (!ImutInfo::isEqual(ImutInfo::KeyOfValue(getValue()),
0122 ImutInfo::KeyOfValue(V)))
0123 return false;
0124
0125
0126 if (!ImutInfo::isDataEqual(ImutInfo::DataOfValue(getValue()),
0127 ImutInfo::DataOfValue(V)))
0128 return false;
0129
0130 return true;
0131 }
0132
0133 bool isElementEqual(const ImutAVLTree* RHS) const {
0134 return isElementEqual(RHS->getValue());
0135 }
0136
0137
0138
0139
0140 bool isEqual(const ImutAVLTree& RHS) const {
0141 if (&RHS == this)
0142 return true;
0143
0144 iterator LItr = begin(), LEnd = end();
0145 iterator RItr = RHS.begin(), REnd = RHS.end();
0146
0147 while (LItr != LEnd && RItr != REnd) {
0148 if (&*LItr == &*RItr) {
0149 LItr.skipSubTree();
0150 RItr.skipSubTree();
0151 continue;
0152 }
0153
0154 if (!LItr->isElementEqual(&*RItr))
0155 return false;
0156
0157 ++LItr;
0158 ++RItr;
0159 }
0160
0161 return LItr == LEnd && RItr == REnd;
0162 }
0163
0164
0165
0166 bool isNotEqual(const ImutAVLTree& RHS) const { return !isEqual(RHS); }
0167
0168
0169
0170
0171 bool contains(key_type_ref K) { return (bool) find(K); }
0172
0173
0174
0175
0176
0177
0178
0179 unsigned validateTree() const {
0180 unsigned HL = getLeft() ? getLeft()->validateTree() : 0;
0181 unsigned HR = getRight() ? getRight()->validateTree() : 0;
0182 (void) HL;
0183 (void) HR;
0184
0185 assert(getHeight() == ( HL > HR ? HL : HR ) + 1
0186 && "Height calculation wrong");
0187
0188 assert((HL > HR ? HL-HR : HR-HL) <= 2
0189 && "Balancing invariant violated");
0190
0191 assert((!getLeft() ||
0192 ImutInfo::isLess(ImutInfo::KeyOfValue(getLeft()->getValue()),
0193 ImutInfo::KeyOfValue(getValue()))) &&
0194 "Value in left child is not less that current value");
0195
0196 assert((!getRight() ||
0197 ImutInfo::isLess(ImutInfo::KeyOfValue(getValue()),
0198 ImutInfo::KeyOfValue(getRight()->getValue()))) &&
0199 "Current value is not less that value of right child");
0200
0201 return getHeight();
0202 }
0203
0204
0205
0206
0207
0208 private:
0209 Factory *factory;
0210 ImutAVLTree *left;
0211 ImutAVLTree *right;
0212 ImutAVLTree *prev = nullptr;
0213 ImutAVLTree *next = nullptr;
0214
0215 unsigned height : 28;
0216 bool IsMutable : 1;
0217 bool IsDigestCached : 1;
0218 bool IsCanonicalized : 1;
0219
0220 value_type value;
0221 uint32_t digest = 0;
0222 uint32_t refCount = 0;
0223
0224
0225
0226
0227
0228 private:
0229
0230
0231 ImutAVLTree(Factory *f, ImutAVLTree* l, ImutAVLTree* r, value_type_ref v,
0232 unsigned height)
0233 : factory(f), left(l), right(r), height(height), IsMutable(true),
0234 IsDigestCached(false), IsCanonicalized(false), value(v)
0235 {
0236 if (left) left->retain();
0237 if (right) right->retain();
0238 }
0239
0240
0241
0242
0243
0244
0245
0246 bool isMutable() const { return IsMutable; }
0247
0248
0249
0250 bool hasCachedDigest() const { return IsDigestCached; }
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265 void markImmutable() {
0266 assert(isMutable() && "Mutable flag already removed.");
0267 IsMutable = false;
0268 }
0269
0270
0271 void markedCachedDigest() {
0272 assert(!hasCachedDigest() && "NoCachedDigest flag already removed.");
0273 IsDigestCached = true;
0274 }
0275
0276
0277
0278 void setHeight(unsigned h) {
0279 assert(isMutable() && "Only a mutable tree can have its height changed.");
0280 height = h;
0281 }
0282
0283 static uint32_t computeDigest(ImutAVLTree *L, ImutAVLTree *R,
0284 value_type_ref V) {
0285 uint32_t digest = 0;
0286
0287 if (L)
0288 digest += L->computeDigest();
0289
0290
0291 FoldingSetNodeID ID;
0292 ImutInfo::Profile(ID,V);
0293 digest += ID.ComputeHash();
0294
0295 if (R)
0296 digest += R->computeDigest();
0297
0298 return digest;
0299 }
0300
0301 uint32_t computeDigest() {
0302
0303
0304 if (hasCachedDigest())
0305 return digest;
0306
0307 uint32_t X = computeDigest(getLeft(), getRight(), getValue());
0308 digest = X;
0309 markedCachedDigest();
0310 return X;
0311 }
0312
0313
0314
0315
0316
0317 public:
0318 void retain() { ++refCount; }
0319
0320 void release() {
0321 assert(refCount > 0);
0322 if (--refCount == 0)
0323 destroy();
0324 }
0325
0326 void destroy() {
0327 if (left)
0328 left->release();
0329 if (right)
0330 right->release();
0331 if (IsCanonicalized) {
0332 if (next)
0333 next->prev = prev;
0334
0335 if (prev)
0336 prev->next = next;
0337 else
0338 factory->Cache[factory->maskCacheIndex(computeDigest())] = next;
0339 }
0340
0341
0342
0343 IsMutable = false;
0344 factory->freeNodes.push_back(this);
0345 }
0346 };
0347
0348 template <typename ImutInfo>
0349 struct IntrusiveRefCntPtrInfo<ImutAVLTree<ImutInfo>> {
0350 static void retain(ImutAVLTree<ImutInfo> *Tree) { Tree->retain(); }
0351 static void release(ImutAVLTree<ImutInfo> *Tree) { Tree->release(); }
0352 };
0353
0354
0355
0356
0357
0358 template <typename ImutInfo >
0359 class ImutAVLFactory {
0360 friend class ImutAVLTree<ImutInfo>;
0361
0362 using TreeTy = ImutAVLTree<ImutInfo>;
0363 using value_type_ref = typename TreeTy::value_type_ref;
0364 using key_type_ref = typename TreeTy::key_type_ref;
0365 using CacheTy = DenseMap<unsigned, TreeTy*>;
0366
0367 CacheTy Cache;
0368 uintptr_t Allocator;
0369 std::vector<TreeTy*> createdNodes;
0370 std::vector<TreeTy*> freeNodes;
0371
0372 bool ownsAllocator() const {
0373 return (Allocator & 0x1) == 0;
0374 }
0375
0376 BumpPtrAllocator& getAllocator() const {
0377 return *reinterpret_cast<BumpPtrAllocator*>(Allocator & ~0x1);
0378 }
0379
0380
0381
0382
0383
0384 public:
0385 ImutAVLFactory()
0386 : Allocator(reinterpret_cast<uintptr_t>(new BumpPtrAllocator())) {}
0387
0388 ImutAVLFactory(BumpPtrAllocator& Alloc)
0389 : Allocator(reinterpret_cast<uintptr_t>(&Alloc) | 0x1) {}
0390
0391 ~ImutAVLFactory() {
0392 if (ownsAllocator()) delete &getAllocator();
0393 }
0394
0395 TreeTy* add(TreeTy* T, value_type_ref V) {
0396 T = add_internal(V,T);
0397 markImmutable(T);
0398 recoverNodes();
0399 return T;
0400 }
0401
0402 TreeTy* remove(TreeTy* T, key_type_ref V) {
0403 T = remove_internal(V,T);
0404 markImmutable(T);
0405 recoverNodes();
0406 return T;
0407 }
0408
0409 TreeTy* getEmptyTree() const { return nullptr; }
0410
0411 protected:
0412
0413
0414
0415
0416
0417
0418
0419 bool isEmpty(TreeTy* T) const { return !T; }
0420 unsigned getHeight(TreeTy* T) const { return T ? T->getHeight() : 0; }
0421 TreeTy* getLeft(TreeTy* T) const { return T->getLeft(); }
0422 TreeTy* getRight(TreeTy* T) const { return T->getRight(); }
0423 value_type_ref getValue(TreeTy* T) const { return T->value; }
0424
0425
0426 static unsigned maskCacheIndex(unsigned I) { return (I & ~0x02); }
0427
0428 unsigned incrementHeight(TreeTy* L, TreeTy* R) const {
0429 unsigned hl = getHeight(L);
0430 unsigned hr = getHeight(R);
0431 return (hl > hr ? hl : hr) + 1;
0432 }
0433
0434 static bool compareTreeWithSection(TreeTy* T,
0435 typename TreeTy::iterator& TI,
0436 typename TreeTy::iterator& TE) {
0437 typename TreeTy::iterator I = T->begin(), E = T->end();
0438 for ( ; I!=E ; ++I, ++TI) {
0439 if (TI == TE || !I->isElementEqual(&*TI))
0440 return false;
0441 }
0442 return true;
0443 }
0444
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455 TreeTy* createNode(TreeTy* L, value_type_ref V, TreeTy* R) {
0456 BumpPtrAllocator& A = getAllocator();
0457 TreeTy* T;
0458 if (!freeNodes.empty()) {
0459 T = freeNodes.back();
0460 freeNodes.pop_back();
0461 assert(T != L);
0462 assert(T != R);
0463 } else {
0464 T = (TreeTy*) A.Allocate<TreeTy>();
0465 }
0466 new (T) TreeTy(this, L, R, V, incrementHeight(L,R));
0467 createdNodes.push_back(T);
0468 return T;
0469 }
0470
0471 TreeTy* createNode(TreeTy* newLeft, TreeTy* oldTree, TreeTy* newRight) {
0472 return createNode(newLeft, getValue(oldTree), newRight);
0473 }
0474
0475 void recoverNodes() {
0476 for (unsigned i = 0, n = createdNodes.size(); i < n; ++i) {
0477 TreeTy *N = createdNodes[i];
0478 if (N->isMutable() && N->refCount == 0)
0479 N->destroy();
0480 }
0481 createdNodes.clear();
0482 }
0483
0484
0485
0486 TreeTy* balanceTree(TreeTy* L, value_type_ref V, TreeTy* R) {
0487 unsigned hl = getHeight(L);
0488 unsigned hr = getHeight(R);
0489
0490 if (hl > hr + 2) {
0491 assert(!isEmpty(L) && "Left tree cannot be empty to have a height >= 2");
0492
0493 TreeTy *LL = getLeft(L);
0494 TreeTy *LR = getRight(L);
0495
0496 if (getHeight(LL) >= getHeight(LR))
0497 return createNode(LL, L, createNode(LR,V,R));
0498
0499 assert(!isEmpty(LR) && "LR cannot be empty because it has a height >= 1");
0500
0501 TreeTy *LRL = getLeft(LR);
0502 TreeTy *LRR = getRight(LR);
0503
0504 return createNode(createNode(LL,L,LRL), LR, createNode(LRR,V,R));
0505 }
0506
0507 if (hr > hl + 2) {
0508 assert(!isEmpty(R) && "Right tree cannot be empty to have a height >= 2");
0509
0510 TreeTy *RL = getLeft(R);
0511 TreeTy *RR = getRight(R);
0512
0513 if (getHeight(RR) >= getHeight(RL))
0514 return createNode(createNode(L,V,RL), R, RR);
0515
0516 assert(!isEmpty(RL) && "RL cannot be empty because it has a height >= 1");
0517
0518 TreeTy *RLL = getLeft(RL);
0519 TreeTy *RLR = getRight(RL);
0520
0521 return createNode(createNode(L,V,RLL), RL, createNode(RLR,R,RR));
0522 }
0523
0524 return createNode(L,V,R);
0525 }
0526
0527
0528
0529
0530 TreeTy* add_internal(value_type_ref V, TreeTy* T) {
0531 if (isEmpty(T))
0532 return createNode(T, V, T);
0533 assert(!T->isMutable());
0534
0535 key_type_ref K = ImutInfo::KeyOfValue(V);
0536 key_type_ref KCurrent = ImutInfo::KeyOfValue(getValue(T));
0537
0538 if (ImutInfo::isEqual(K,KCurrent))
0539 return createNode(getLeft(T), V, getRight(T));
0540 else if (ImutInfo::isLess(K,KCurrent))
0541 return balanceTree(add_internal(V, getLeft(T)), getValue(T), getRight(T));
0542 else
0543 return balanceTree(getLeft(T), getValue(T), add_internal(V, getRight(T)));
0544 }
0545
0546
0547
0548
0549
0550 TreeTy* remove_internal(key_type_ref K, TreeTy* T) {
0551 if (isEmpty(T))
0552 return T;
0553
0554 assert(!T->isMutable());
0555
0556 key_type_ref KCurrent = ImutInfo::KeyOfValue(getValue(T));
0557
0558 if (ImutInfo::isEqual(K,KCurrent)) {
0559 return combineTrees(getLeft(T), getRight(T));
0560 } else if (ImutInfo::isLess(K,KCurrent)) {
0561 return balanceTree(remove_internal(K, getLeft(T)),
0562 getValue(T), getRight(T));
0563 } else {
0564 return balanceTree(getLeft(T), getValue(T),
0565 remove_internal(K, getRight(T)));
0566 }
0567 }
0568
0569 TreeTy* combineTrees(TreeTy* L, TreeTy* R) {
0570 if (isEmpty(L))
0571 return R;
0572 if (isEmpty(R))
0573 return L;
0574 TreeTy* OldNode;
0575 TreeTy* newRight = removeMinBinding(R,OldNode);
0576 return balanceTree(L, getValue(OldNode), newRight);
0577 }
0578
0579 TreeTy* removeMinBinding(TreeTy* T, TreeTy*& Noderemoved) {
0580 assert(!isEmpty(T));
0581 if (isEmpty(getLeft(T))) {
0582 Noderemoved = T;
0583 return getRight(T);
0584 }
0585 return balanceTree(removeMinBinding(getLeft(T), Noderemoved),
0586 getValue(T), getRight(T));
0587 }
0588
0589
0590
0591 void markImmutable(TreeTy* T) {
0592 if (!T || !T->isMutable())
0593 return;
0594 T->markImmutable();
0595 markImmutable(getLeft(T));
0596 markImmutable(getRight(T));
0597 }
0598
0599 public:
0600 TreeTy *getCanonicalTree(TreeTy *TNew) {
0601 if (!TNew)
0602 return nullptr;
0603
0604 if (TNew->IsCanonicalized)
0605 return TNew;
0606
0607
0608
0609 unsigned digest = TNew->computeDigest();
0610 TreeTy *&entry = Cache[maskCacheIndex(digest)];
0611 do {
0612 if (!entry)
0613 break;
0614 for (TreeTy *T = entry ; T != nullptr; T = T->next) {
0615
0616 typename TreeTy::iterator TI = T->begin(), TE = T->end();
0617 if (!compareTreeWithSection(TNew, TI, TE))
0618 continue;
0619 if (TI != TE)
0620 continue;
0621
0622 if (TNew->refCount == 0)
0623 TNew->destroy();
0624 return T;
0625 }
0626 entry->prev = TNew;
0627 TNew->next = entry;
0628 }
0629 while (false);
0630
0631 entry = TNew;
0632 TNew->IsCanonicalized = true;
0633 return TNew;
0634 }
0635 };
0636
0637
0638
0639
0640
0641 template <typename ImutInfo> class ImutAVLTreeGenericIterator {
0642 SmallVector<uintptr_t,20> stack;
0643
0644 public:
0645 using iterator_category = std::bidirectional_iterator_tag;
0646 using value_type = ImutAVLTree<ImutInfo>;
0647 using difference_type = std::ptrdiff_t;
0648 using pointer = value_type *;
0649 using reference = value_type &;
0650
0651 enum VisitFlag { VisitedNone=0x0, VisitedLeft=0x1, VisitedRight=0x3,
0652 Flags=0x3 };
0653
0654 using TreeTy = ImutAVLTree<ImutInfo>;
0655
0656 ImutAVLTreeGenericIterator() = default;
0657 ImutAVLTreeGenericIterator(const TreeTy *Root) {
0658 if (Root) stack.push_back(reinterpret_cast<uintptr_t>(Root));
0659 }
0660
0661 TreeTy &operator*() const {
0662 assert(!stack.empty());
0663 return *reinterpret_cast<TreeTy *>(stack.back() & ~Flags);
0664 }
0665 TreeTy *operator->() const { return &*this; }
0666
0667 uintptr_t getVisitState() const {
0668 assert(!stack.empty());
0669 return stack.back() & Flags;
0670 }
0671
0672 bool atEnd() const { return stack.empty(); }
0673
0674 bool atBeginning() const {
0675 return stack.size() == 1 && getVisitState() == VisitedNone;
0676 }
0677
0678 void skipToParent() {
0679 assert(!stack.empty());
0680 stack.pop_back();
0681 if (stack.empty())
0682 return;
0683 switch (getVisitState()) {
0684 case VisitedNone:
0685 stack.back() |= VisitedLeft;
0686 break;
0687 case VisitedLeft:
0688 stack.back() |= VisitedRight;
0689 break;
0690 default:
0691 llvm_unreachable("Unreachable.");
0692 }
0693 }
0694
0695 bool operator==(const ImutAVLTreeGenericIterator &x) const {
0696 return stack == x.stack;
0697 }
0698
0699 bool operator!=(const ImutAVLTreeGenericIterator &x) const {
0700 return !(*this == x);
0701 }
0702
0703 ImutAVLTreeGenericIterator &operator++() {
0704 assert(!stack.empty());
0705 TreeTy* Current = reinterpret_cast<TreeTy*>(stack.back() & ~Flags);
0706 assert(Current);
0707 switch (getVisitState()) {
0708 case VisitedNone:
0709 if (TreeTy* L = Current->getLeft())
0710 stack.push_back(reinterpret_cast<uintptr_t>(L));
0711 else
0712 stack.back() |= VisitedLeft;
0713 break;
0714 case VisitedLeft:
0715 if (TreeTy* R = Current->getRight())
0716 stack.push_back(reinterpret_cast<uintptr_t>(R));
0717 else
0718 stack.back() |= VisitedRight;
0719 break;
0720 case VisitedRight:
0721 skipToParent();
0722 break;
0723 default:
0724 llvm_unreachable("Unreachable.");
0725 }
0726 return *this;
0727 }
0728
0729 ImutAVLTreeGenericIterator &operator--() {
0730 assert(!stack.empty());
0731 TreeTy* Current = reinterpret_cast<TreeTy*>(stack.back() & ~Flags);
0732 assert(Current);
0733 switch (getVisitState()) {
0734 case VisitedNone:
0735 stack.pop_back();
0736 break;
0737 case VisitedLeft:
0738 stack.back() &= ~Flags;
0739 if (TreeTy* L = Current->getLeft())
0740 stack.push_back(reinterpret_cast<uintptr_t>(L) | VisitedRight);
0741 break;
0742 case VisitedRight:
0743 stack.back() &= ~Flags;
0744 stack.back() |= VisitedLeft;
0745 if (TreeTy* R = Current->getRight())
0746 stack.push_back(reinterpret_cast<uintptr_t>(R) | VisitedRight);
0747 break;
0748 default:
0749 llvm_unreachable("Unreachable.");
0750 }
0751 return *this;
0752 }
0753 };
0754
0755 template <typename ImutInfo> class ImutAVLTreeInOrderIterator {
0756 using InternalIteratorTy = ImutAVLTreeGenericIterator<ImutInfo>;
0757
0758 InternalIteratorTy InternalItr;
0759
0760 public:
0761 using iterator_category = std::bidirectional_iterator_tag;
0762 using value_type = ImutAVLTree<ImutInfo>;
0763 using difference_type = std::ptrdiff_t;
0764 using pointer = value_type *;
0765 using reference = value_type &;
0766
0767 using TreeTy = ImutAVLTree<ImutInfo>;
0768
0769 ImutAVLTreeInOrderIterator(const TreeTy* Root) : InternalItr(Root) {
0770 if (Root)
0771 ++*this;
0772 }
0773
0774 ImutAVLTreeInOrderIterator() : InternalItr() {}
0775
0776 bool operator==(const ImutAVLTreeInOrderIterator &x) const {
0777 return InternalItr == x.InternalItr;
0778 }
0779
0780 bool operator!=(const ImutAVLTreeInOrderIterator &x) const {
0781 return !(*this == x);
0782 }
0783
0784 TreeTy &operator*() const { return *InternalItr; }
0785 TreeTy *operator->() const { return &*InternalItr; }
0786
0787 ImutAVLTreeInOrderIterator &operator++() {
0788 do ++InternalItr;
0789 while (!InternalItr.atEnd() &&
0790 InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft);
0791
0792 return *this;
0793 }
0794
0795 ImutAVLTreeInOrderIterator &operator--() {
0796 do --InternalItr;
0797 while (!InternalItr.atBeginning() &&
0798 InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft);
0799
0800 return *this;
0801 }
0802
0803 void skipSubTree() {
0804 InternalItr.skipToParent();
0805
0806 while (!InternalItr.atEnd() &&
0807 InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft)
0808 ++InternalItr;
0809 }
0810 };
0811
0812
0813
0814 template <typename T>
0815 struct ImutAVLValueIterator
0816 : iterator_adaptor_base<
0817 ImutAVLValueIterator<T>, typename T::TreeTy::iterator,
0818 typename std::iterator_traits<
0819 typename T::TreeTy::iterator>::iterator_category,
0820 const typename T::value_type> {
0821 ImutAVLValueIterator() = default;
0822 explicit ImutAVLValueIterator(typename T::TreeTy *Tree)
0823 : ImutAVLValueIterator::iterator_adaptor_base(Tree) {}
0824
0825 typename ImutAVLValueIterator::reference operator*() const {
0826 return this->I->getValue();
0827 }
0828 };
0829
0830
0831
0832
0833
0834
0835
0836
0837 template <typename T>
0838 struct ImutProfileInfo {
0839 using value_type = const T;
0840 using value_type_ref = const T&;
0841
0842 static void Profile(FoldingSetNodeID &ID, value_type_ref X) {
0843 FoldingSetTrait<T>::Profile(X,ID);
0844 }
0845 };
0846
0847
0848 template <typename T>
0849 struct ImutProfileInteger {
0850 using value_type = const T;
0851 using value_type_ref = const T&;
0852
0853 static void Profile(FoldingSetNodeID &ID, value_type_ref X) {
0854 ID.AddInteger(X);
0855 }
0856 };
0857
0858 #define PROFILE_INTEGER_INFO(X)\
0859 template<> struct ImutProfileInfo<X> : ImutProfileInteger<X> {};
0860
0861 PROFILE_INTEGER_INFO(char)
0862 PROFILE_INTEGER_INFO(unsigned char)
0863 PROFILE_INTEGER_INFO(short)
0864 PROFILE_INTEGER_INFO(unsigned short)
0865 PROFILE_INTEGER_INFO(unsigned)
0866 PROFILE_INTEGER_INFO(signed)
0867 PROFILE_INTEGER_INFO(long)
0868 PROFILE_INTEGER_INFO(unsigned long)
0869 PROFILE_INTEGER_INFO(long long)
0870 PROFILE_INTEGER_INFO(unsigned long long)
0871
0872 #undef PROFILE_INTEGER_INFO
0873
0874
0875 template <>
0876 struct ImutProfileInfo<bool> {
0877 using value_type = const bool;
0878 using value_type_ref = const bool&;
0879
0880 static void Profile(FoldingSetNodeID &ID, value_type_ref X) {
0881 ID.AddBoolean(X);
0882 }
0883 };
0884
0885
0886
0887 template <typename T>
0888 struct ImutProfileInfo<T*> {
0889 using value_type = const T*;
0890 using value_type_ref = value_type;
0891
0892 static void Profile(FoldingSetNodeID &ID, value_type_ref X) {
0893 ID.AddPointer(X);
0894 }
0895 };
0896
0897
0898
0899
0900
0901
0902
0903
0904
0905
0906
0907 template <typename T>
0908 struct ImutContainerInfo : public ImutProfileInfo<T> {
0909 using value_type = typename ImutProfileInfo<T>::value_type;
0910 using value_type_ref = typename ImutProfileInfo<T>::value_type_ref;
0911 using key_type = value_type;
0912 using key_type_ref = value_type_ref;
0913 using data_type = bool;
0914 using data_type_ref = bool;
0915
0916 static key_type_ref KeyOfValue(value_type_ref D) { return D; }
0917 static data_type_ref DataOfValue(value_type_ref) { return true; }
0918
0919 static bool isEqual(key_type_ref LHS, key_type_ref RHS) {
0920 return std::equal_to<key_type>()(LHS,RHS);
0921 }
0922
0923 static bool isLess(key_type_ref LHS, key_type_ref RHS) {
0924 return std::less<key_type>()(LHS,RHS);
0925 }
0926
0927 static bool isDataEqual(data_type_ref, data_type_ref) { return true; }
0928 };
0929
0930
0931
0932
0933 template <typename T>
0934 struct ImutContainerInfo<T*> : public ImutProfileInfo<T*> {
0935 using value_type = typename ImutProfileInfo<T*>::value_type;
0936 using value_type_ref = typename ImutProfileInfo<T*>::value_type_ref;
0937 using key_type = value_type;
0938 using key_type_ref = value_type_ref;
0939 using data_type = bool;
0940 using data_type_ref = bool;
0941
0942 static key_type_ref KeyOfValue(value_type_ref D) { return D; }
0943 static data_type_ref DataOfValue(value_type_ref) { return true; }
0944
0945 static bool isEqual(key_type_ref LHS, key_type_ref RHS) { return LHS == RHS; }
0946
0947 static bool isLess(key_type_ref LHS, key_type_ref RHS) { return LHS < RHS; }
0948
0949 static bool isDataEqual(data_type_ref, data_type_ref) { return true; }
0950 };
0951
0952
0953
0954
0955
0956 template <typename ValT, typename ValInfo = ImutContainerInfo<ValT>>
0957 class ImmutableSet {
0958 public:
0959 using value_type = typename ValInfo::value_type;
0960 using value_type_ref = typename ValInfo::value_type_ref;
0961 using TreeTy = ImutAVLTree<ValInfo>;
0962
0963 private:
0964 IntrusiveRefCntPtr<TreeTy> Root;
0965
0966 public:
0967
0968
0969
0970
0971 explicit ImmutableSet(TreeTy *R) : Root(R) {}
0972
0973 class Factory {
0974 typename TreeTy::Factory F;
0975 const bool Canonicalize;
0976
0977 public:
0978 Factory(bool canonicalize = true)
0979 : Canonicalize(canonicalize) {}
0980
0981 Factory(BumpPtrAllocator& Alloc, bool canonicalize = true)
0982 : F(Alloc), Canonicalize(canonicalize) {}
0983
0984 Factory(const Factory& RHS) = delete;
0985 void operator=(const Factory& RHS) = delete;
0986
0987
0988 ImmutableSet getEmptySet() {
0989 return ImmutableSet(F.getEmptyTree());
0990 }
0991
0992
0993
0994
0995
0996
0997
0998
0999 [[nodiscard]] ImmutableSet add(ImmutableSet Old, value_type_ref V) {
1000 TreeTy *NewT = F.add(Old.Root.get(), V);
1001 return ImmutableSet(Canonicalize ? F.getCanonicalTree(NewT) : NewT);
1002 }
1003
1004
1005
1006
1007
1008
1009
1010
1011 [[nodiscard]] ImmutableSet remove(ImmutableSet Old, value_type_ref V) {
1012 TreeTy *NewT = F.remove(Old.Root.get(), V);
1013 return ImmutableSet(Canonicalize ? F.getCanonicalTree(NewT) : NewT);
1014 }
1015
1016 BumpPtrAllocator& getAllocator() { return F.getAllocator(); }
1017
1018 typename TreeTy::Factory *getTreeFactory() const {
1019 return const_cast<typename TreeTy::Factory *>(&F);
1020 }
1021 };
1022
1023 friend class Factory;
1024
1025
1026 bool contains(value_type_ref V) const {
1027 return Root ? Root->contains(V) : false;
1028 }
1029
1030 bool operator==(const ImmutableSet &RHS) const {
1031 return Root && RHS.Root ? Root->isEqual(*RHS.Root.get()) : Root == RHS.Root;
1032 }
1033
1034 bool operator!=(const ImmutableSet &RHS) const {
1035 return Root && RHS.Root ? Root->isNotEqual(*RHS.Root.get())
1036 : Root != RHS.Root;
1037 }
1038
1039 TreeTy *getRoot() {
1040 if (Root) { Root->retain(); }
1041 return Root.get();
1042 }
1043
1044 TreeTy *getRootWithoutRetain() const { return Root.get(); }
1045
1046
1047 bool isEmpty() const { return !Root; }
1048
1049
1050
1051 bool isSingleton() const { return getHeight() == 1; }
1052
1053
1054
1055
1056
1057 using iterator = ImutAVLValueIterator<ImmutableSet>;
1058
1059 iterator begin() const { return iterator(Root.get()); }
1060 iterator end() const { return iterator(); }
1061
1062
1063
1064
1065
1066 unsigned getHeight() const { return Root ? Root->getHeight() : 0; }
1067
1068 static void Profile(FoldingSetNodeID &ID, const ImmutableSet &S) {
1069 ID.AddPointer(S.Root.get());
1070 }
1071
1072 void Profile(FoldingSetNodeID &ID) const { return Profile(ID, *this); }
1073
1074
1075
1076
1077
1078 void validateTree() const { if (Root) Root->validateTree(); }
1079 };
1080
1081
1082 template <typename ValT, typename ValInfo = ImutContainerInfo<ValT>>
1083 class ImmutableSetRef {
1084 public:
1085 using value_type = typename ValInfo::value_type;
1086 using value_type_ref = typename ValInfo::value_type_ref;
1087 using TreeTy = ImutAVLTree<ValInfo>;
1088 using FactoryTy = typename TreeTy::Factory;
1089
1090 private:
1091 IntrusiveRefCntPtr<TreeTy> Root;
1092 FactoryTy *Factory;
1093
1094 public:
1095
1096
1097
1098
1099 ImmutableSetRef(TreeTy *R, FactoryTy *F) : Root(R), Factory(F) {}
1100
1101 static ImmutableSetRef getEmptySet(FactoryTy *F) {
1102 return ImmutableSetRef(0, F);
1103 }
1104
1105 ImmutableSetRef add(value_type_ref V) {
1106 return ImmutableSetRef(Factory->add(Root.get(), V), Factory);
1107 }
1108
1109 ImmutableSetRef remove(value_type_ref V) {
1110 return ImmutableSetRef(Factory->remove(Root.get(), V), Factory);
1111 }
1112
1113
1114 bool contains(value_type_ref V) const {
1115 return Root ? Root->contains(V) : false;
1116 }
1117
1118 ImmutableSet<ValT> asImmutableSet(bool canonicalize = true) const {
1119 return ImmutableSet<ValT>(
1120 canonicalize ? Factory->getCanonicalTree(Root.get()) : Root.get());
1121 }
1122
1123 TreeTy *getRootWithoutRetain() const { return Root.get(); }
1124
1125 bool operator==(const ImmutableSetRef &RHS) const {
1126 return Root && RHS.Root ? Root->isEqual(*RHS.Root.get()) : Root == RHS.Root;
1127 }
1128
1129 bool operator!=(const ImmutableSetRef &RHS) const {
1130 return Root && RHS.Root ? Root->isNotEqual(*RHS.Root.get())
1131 : Root != RHS.Root;
1132 }
1133
1134
1135 bool isEmpty() const { return !Root; }
1136
1137
1138
1139 bool isSingleton() const { return getHeight() == 1; }
1140
1141
1142
1143
1144
1145 using iterator = ImutAVLValueIterator<ImmutableSetRef>;
1146
1147 iterator begin() const { return iterator(Root.get()); }
1148 iterator end() const { return iterator(); }
1149
1150
1151
1152
1153
1154 unsigned getHeight() const { return Root ? Root->getHeight() : 0; }
1155
1156 static void Profile(FoldingSetNodeID &ID, const ImmutableSetRef &S) {
1157 ID.AddPointer(S.Root.get());
1158 }
1159
1160 void Profile(FoldingSetNodeID &ID) const { return Profile(ID, *this); }
1161
1162
1163
1164
1165
1166 void validateTree() const { if (Root) Root->validateTree(); }
1167 };
1168
1169 }
1170
1171 #endif