1f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot//===--- ImmutableSet.h - Immutable (functional) set interface --*- C++ -*-===//
2f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot//
3f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot//                     The LLVM Compiler Infrastructure
4f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot//
5f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot// This file is distributed under the University of Illinois Open Source
6f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot// License. See LICENSE.TXT for details.
7f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot//
8f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot//===----------------------------------------------------------------------===//
9f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot//
10f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot// This file defines the ImutAVLTree and ImmutableSet classes.
11f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot//
12f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot//===----------------------------------------------------------------------===//
13f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
14f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot#ifndef LLVM_ADT_IMMUTABLESET_H
15f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot#define LLVM_ADT_IMMUTABLESET_H
16f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
17f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot#include "llvm/ADT/DenseMap.h"
18f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot#include "llvm/ADT/FoldingSet.h"
19f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot#include "llvm/ADT/SmallVector.h"
20f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot#include "llvm/ADT/iterator.h"
21f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot#include "llvm/Support/Allocator.h"
22f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot#include "llvm/Support/ErrorHandling.h"
23f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot#include <cassert>
24f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot#include <cstdint>
25f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot#include <functional>
26f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot#include <iterator>
27f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot#include <new>
28f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot#include <vector>
29f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
30f3014761c955345d6e05491608e73228d014afbandroid-build-team Robotnamespace llvm {
31f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
32f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot//===----------------------------------------------------------------------===//
33f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot// Immutable AVL-Tree Definition.
34f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot//===----------------------------------------------------------------------===//
35f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
36f3014761c955345d6e05491608e73228d014afbandroid-build-team Robottemplate <typename ImutInfo> class ImutAVLFactory;
37f3014761c955345d6e05491608e73228d014afbandroid-build-team Robottemplate <typename ImutInfo> class ImutIntervalAVLFactory;
38f3014761c955345d6e05491608e73228d014afbandroid-build-team Robottemplate <typename ImutInfo> class ImutAVLTreeInOrderIterator;
39f3014761c955345d6e05491608e73228d014afbandroid-build-team Robottemplate <typename ImutInfo> class ImutAVLTreeGenericIterator;
40f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
41f3014761c955345d6e05491608e73228d014afbandroid-build-team Robottemplate <typename ImutInfo >
42f3014761c955345d6e05491608e73228d014afbandroid-build-team Robotclass ImutAVLTree {
43f3014761c955345d6e05491608e73228d014afbandroid-build-team Robotpublic:
44f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using key_type_ref = typename ImutInfo::key_type_ref;
45f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using value_type = typename ImutInfo::value_type;
46f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using value_type_ref = typename ImutInfo::value_type_ref;
47f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using Factory = ImutAVLFactory<ImutInfo>;
48f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using iterator = ImutAVLTreeInOrderIterator<ImutInfo>;
49f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
50f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  friend class ImutAVLFactory<ImutInfo>;
51f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  friend class ImutIntervalAVLFactory<ImutInfo>;
52f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  friend class ImutAVLTreeGenericIterator<ImutInfo>;
53f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
54f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  //===----------------------------------------------------===//
55f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // Public Interface.
56f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  //===----------------------------------------------------===//
57f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
58f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// Return a pointer to the left subtree.  This value
59f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///  is NULL if there is no left subtree.
60f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ImutAVLTree *getLeft() const { return left; }
61f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
62f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// Return a pointer to the right subtree.  This value is
63f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///  NULL if there is no right subtree.
64f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ImutAVLTree *getRight() const { return right; }
65f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
66f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// getHeight - Returns the height of the tree.  A tree with no subtrees
67f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///  has a height of 1.
68f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  unsigned getHeight() const { return height; }
69f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
70f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// getValue - Returns the data value associated with the tree node.
71f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  const value_type& getValue() const { return value; }
72f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
73f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// find - Finds the subtree associated with the specified key value.
74f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///  This method returns NULL if no matching subtree is found.
75f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ImutAVLTree* find(key_type_ref K) {
76f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    ImutAVLTree *T = this;
77f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    while (T) {
78f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      key_type_ref CurrentKey = ImutInfo::KeyOfValue(T->getValue());
79f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      if (ImutInfo::isEqual(K,CurrentKey))
80f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        return T;
81f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      else if (ImutInfo::isLess(K,CurrentKey))
82f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        T = T->getLeft();
83f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      else
84f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        T = T->getRight();
85f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    }
86f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return nullptr;
87f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
88f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
89f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// getMaxElement - Find the subtree associated with the highest ranged
90f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///  key value.
91f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ImutAVLTree* getMaxElement() {
92f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    ImutAVLTree *T = this;
93f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    ImutAVLTree *Right = T->getRight();
94f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    while (Right) { T = Right; Right = T->getRight(); }
95f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return T;
96f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
97f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
98f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// size - Returns the number of nodes in the tree, which includes
99f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///  both leaves and non-leaf nodes.
100f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  unsigned size() const {
101f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    unsigned n = 1;
102f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (const ImutAVLTree* L = getLeft())
103f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      n += L->size();
104f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (const ImutAVLTree* R = getRight())
105f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      n += R->size();
106f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return n;
107f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
108f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
109f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// begin - Returns an iterator that iterates over the nodes of the tree
110f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///  in an inorder traversal.  The returned iterator thus refers to the
111f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///  the tree node with the minimum data element.
112f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  iterator begin() const { return iterator(this); }
113f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
114f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// end - Returns an iterator for the tree that denotes the end of an
115f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///  inorder traversal.
116f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  iterator end() const { return iterator(); }
117f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
118f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  bool isElementEqual(value_type_ref V) const {
119f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    // Compare the keys.
120f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (!ImutInfo::isEqual(ImutInfo::KeyOfValue(getValue()),
121f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot                           ImutInfo::KeyOfValue(V)))
122f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      return false;
123f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
124f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    // Also compare the data values.
125f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (!ImutInfo::isDataEqual(ImutInfo::DataOfValue(getValue()),
126f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot                               ImutInfo::DataOfValue(V)))
127f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      return false;
128f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
129f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return true;
130f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
131f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
132f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  bool isElementEqual(const ImutAVLTree* RHS) const {
133f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return isElementEqual(RHS->getValue());
134f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
135f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
136f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// isEqual - Compares two trees for structural equality and returns true
137f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///   if they are equal.  This worst case performance of this operation is
138f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  //    linear in the sizes of the trees.
139f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  bool isEqual(const ImutAVLTree& RHS) const {
140f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (&RHS == this)
141f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      return true;
142f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
143f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    iterator LItr = begin(), LEnd = end();
144f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    iterator RItr = RHS.begin(), REnd = RHS.end();
145f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
146f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    while (LItr != LEnd && RItr != REnd) {
147f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      if (&*LItr == &*RItr) {
148f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        LItr.skipSubTree();
149f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        RItr.skipSubTree();
150f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        continue;
151f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      }
152f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
153f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      if (!LItr->isElementEqual(&*RItr))
154f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        return false;
155f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
156f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      ++LItr;
157f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      ++RItr;
158f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    }
159f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
160f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return LItr == LEnd && RItr == REnd;
161f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
162f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
163f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// isNotEqual - Compares two trees for structural inequality.  Performance
164f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///  is the same is isEqual.
165f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  bool isNotEqual(const ImutAVLTree& RHS) const { return !isEqual(RHS); }
166f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
167f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// contains - Returns true if this tree contains a subtree (node) that
168f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///  has an data element that matches the specified key.  Complexity
169f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///  is logarithmic in the size of the tree.
170f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  bool contains(key_type_ref K) { return (bool) find(K); }
171f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
172f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// foreach - A member template the accepts invokes operator() on a functor
173f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///  object (specifed by Callback) for every node/subtree in the tree.
174f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///  Nodes are visited using an inorder traversal.
175f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  template <typename Callback>
176f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  void foreach(Callback& C) {
177f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (ImutAVLTree* L = getLeft())
178f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      L->foreach(C);
179f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
180f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    C(value);
181f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
182f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (ImutAVLTree* R = getRight())
183f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      R->foreach(C);
184f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
185f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
186f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// validateTree - A utility method that checks that the balancing and
187f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///  ordering invariants of the tree are satisifed.  It is a recursive
188f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///  method that returns the height of the tree, which is then consumed
189f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///  by the enclosing validateTree call.  External callers should ignore the
190f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///  return value.  An invalid tree will cause an assertion to fire in
191f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///  a debug build.
192f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  unsigned validateTree() const {
193f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    unsigned HL = getLeft() ? getLeft()->validateTree() : 0;
194f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    unsigned HR = getRight() ? getRight()->validateTree() : 0;
195f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    (void) HL;
196f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    (void) HR;
197f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
198f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    assert(getHeight() == ( HL > HR ? HL : HR ) + 1
199f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot            && "Height calculation wrong");
200f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
201f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    assert((HL > HR ? HL-HR : HR-HL) <= 2
202f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot           && "Balancing invariant violated");
203f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
204f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    assert((!getLeft() ||
205f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot            ImutInfo::isLess(ImutInfo::KeyOfValue(getLeft()->getValue()),
206f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot                             ImutInfo::KeyOfValue(getValue()))) &&
207f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot           "Value in left child is not less that current value");
208f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
209f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
210f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    assert(!(getRight() ||
211f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot             ImutInfo::isLess(ImutInfo::KeyOfValue(getValue()),
212f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot                              ImutInfo::KeyOfValue(getRight()->getValue()))) &&
213f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot           "Current value is not less that value of right child");
214f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
215f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return getHeight();
216f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
217f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
218f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  //===----------------------------------------------------===//
219f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // Internal values.
220f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  //===----------------------------------------------------===//
221f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
222f3014761c955345d6e05491608e73228d014afbandroid-build-team Robotprivate:
223f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  Factory *factory;
224f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ImutAVLTree *left;
225f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ImutAVLTree *right;
226f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ImutAVLTree *prev = nullptr;
227f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ImutAVLTree *next = nullptr;
228f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
229f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  unsigned height : 28;
230f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  bool IsMutable : 1;
231f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  bool IsDigestCached : 1;
232f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  bool IsCanonicalized : 1;
233f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
234f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  value_type value;
235f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  uint32_t digest = 0;
236f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  uint32_t refCount = 0;
237f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
238f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  //===----------------------------------------------------===//
239f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // Internal methods (node manipulation; used by Factory).
240f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  //===----------------------------------------------------===//
241f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
242f3014761c955345d6e05491608e73228d014afbandroid-build-team Robotprivate:
243f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// ImutAVLTree - Internal constructor that is only called by
244f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///   ImutAVLFactory.
245f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ImutAVLTree(Factory *f, ImutAVLTree* l, ImutAVLTree* r, value_type_ref v,
246f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot              unsigned height)
247f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    : factory(f), left(l), right(r), height(height), IsMutable(true),
248f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      IsDigestCached(false), IsCanonicalized(false), value(v)
249f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  {
250f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (left) left->retain();
251f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (right) right->retain();
252f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
253f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
254f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// isMutable - Returns true if the left and right subtree references
255f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///  (as well as height) can be changed.  If this method returns false,
256f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///  the tree is truly immutable.  Trees returned from an ImutAVLFactory
257f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///  object should always have this method return true.  Further, if this
258f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///  method returns false for an instance of ImutAVLTree, all subtrees
259f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///  will also have this method return false.  The converse is not true.
260f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  bool isMutable() const { return IsMutable; }
261f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
262f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// hasCachedDigest - Returns true if the digest for this tree is cached.
263f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///  This can only be true if the tree is immutable.
264f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  bool hasCachedDigest() const { return IsDigestCached; }
265f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
266f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  //===----------------------------------------------------===//
267f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // Mutating operations.  A tree root can be manipulated as
268f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // long as its reference has not "escaped" from internal
269f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // methods of a factory object (see below).  When a tree
270f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // pointer is externally viewable by client code, the
271f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // internal "mutable bit" is cleared to mark the tree
272f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // immutable.  Note that a tree that still has its mutable
273f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // bit set may have children (subtrees) that are themselves
274f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // immutable.
275f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  //===----------------------------------------------------===//
276f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
277f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// markImmutable - Clears the mutable flag for a tree.  After this happens,
278f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///   it is an error to call setLeft(), setRight(), and setHeight().
279f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  void markImmutable() {
280f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    assert(isMutable() && "Mutable flag already removed.");
281f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    IsMutable = false;
282f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
283f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
284f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// markedCachedDigest - Clears the NoCachedDigest flag for a tree.
285f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  void markedCachedDigest() {
286f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    assert(!hasCachedDigest() && "NoCachedDigest flag already removed.");
287f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    IsDigestCached = true;
288f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
289f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
290f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// setHeight - Changes the height of the tree.  Used internally by
291f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///  ImutAVLFactory.
292f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  void setHeight(unsigned h) {
293f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    assert(isMutable() && "Only a mutable tree can have its height changed.");
294f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    height = h;
295f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
296f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
297f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  static uint32_t computeDigest(ImutAVLTree *L, ImutAVLTree *R,
298f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot                                value_type_ref V) {
299f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    uint32_t digest = 0;
300f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
301f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (L)
302f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      digest += L->computeDigest();
303f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
304f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    // Compute digest of stored data.
305f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    FoldingSetNodeID ID;
306f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    ImutInfo::Profile(ID,V);
307f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    digest += ID.ComputeHash();
308f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
309f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (R)
310f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      digest += R->computeDigest();
311f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
312f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return digest;
313f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
314f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
315f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  uint32_t computeDigest() {
316f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    // Check the lowest bit to determine if digest has actually been
317f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    // pre-computed.
318f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (hasCachedDigest())
319f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      return digest;
320f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
321f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    uint32_t X = computeDigest(getLeft(), getRight(), getValue());
322f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    digest = X;
323f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    markedCachedDigest();
324f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return X;
325f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
326f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
327f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  //===----------------------------------------------------===//
328f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // Reference count operations.
329f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  //===----------------------------------------------------===//
330f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
331f3014761c955345d6e05491608e73228d014afbandroid-build-team Robotpublic:
332f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  void retain() { ++refCount; }
333f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
334f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  void release() {
335f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    assert(refCount > 0);
336f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (--refCount == 0)
337f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      destroy();
338f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
339f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
340f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  void destroy() {
341f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (left)
342f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      left->release();
343f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (right)
344f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      right->release();
345f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (IsCanonicalized) {
346f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      if (next)
347f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        next->prev = prev;
348f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
349f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      if (prev)
350f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        prev->next = next;
351f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      else
352f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        factory->Cache[factory->maskCacheIndex(computeDigest())] = next;
353f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    }
354f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
355f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    // We need to clear the mutability bit in case we are
356f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    // destroying the node as part of a sweep in ImutAVLFactory::recoverNodes().
357f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    IsMutable = false;
358f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    factory->freeNodes.push_back(this);
359f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
360f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot};
361f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
362f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot//===----------------------------------------------------------------------===//
363f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot// Immutable AVL-Tree Factory class.
364f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot//===----------------------------------------------------------------------===//
365f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
366f3014761c955345d6e05491608e73228d014afbandroid-build-team Robottemplate <typename ImutInfo >
367f3014761c955345d6e05491608e73228d014afbandroid-build-team Robotclass ImutAVLFactory {
368f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  friend class ImutAVLTree<ImutInfo>;
369f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
370f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using TreeTy = ImutAVLTree<ImutInfo>;
371f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using value_type_ref = typename TreeTy::value_type_ref;
372f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using key_type_ref = typename TreeTy::key_type_ref;
373f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using CacheTy = DenseMap<unsigned, TreeTy*>;
374f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
375f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  CacheTy Cache;
376f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  uintptr_t Allocator;
377f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  std::vector<TreeTy*> createdNodes;
378f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  std::vector<TreeTy*> freeNodes;
379f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
380f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  bool ownsAllocator() const {
381f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return (Allocator & 0x1) == 0;
382f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
383f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
384f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  BumpPtrAllocator& getAllocator() const {
385f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return *reinterpret_cast<BumpPtrAllocator*>(Allocator & ~0x1);
386f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
387f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
388f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  //===--------------------------------------------------===//
389f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // Public interface.
390f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  //===--------------------------------------------------===//
391f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
392f3014761c955345d6e05491608e73228d014afbandroid-build-team Robotpublic:
393f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ImutAVLFactory()
394f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    : Allocator(reinterpret_cast<uintptr_t>(new BumpPtrAllocator())) {}
395f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
396f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ImutAVLFactory(BumpPtrAllocator& Alloc)
397f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    : Allocator(reinterpret_cast<uintptr_t>(&Alloc) | 0x1) {}
398f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
399f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ~ImutAVLFactory() {
400f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (ownsAllocator()) delete &getAllocator();
401f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
402f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
403f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  TreeTy* add(TreeTy* T, value_type_ref V) {
404f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    T = add_internal(V,T);
405f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    markImmutable(T);
406f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    recoverNodes();
407f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return T;
408f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
409f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
410f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  TreeTy* remove(TreeTy* T, key_type_ref V) {
411f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    T = remove_internal(V,T);
412f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    markImmutable(T);
413f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    recoverNodes();
414f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return T;
415f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
416f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
417f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  TreeTy* getEmptyTree() const { return nullptr; }
418f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
419f3014761c955345d6e05491608e73228d014afbandroid-build-team Robotprotected:
420f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  //===--------------------------------------------------===//
421f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // A bunch of quick helper functions used for reasoning
422f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // about the properties of trees and their children.
423f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // These have succinct names so that the balancing code
424f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // is as terse (and readable) as possible.
425f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  //===--------------------------------------------------===//
426f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
427f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  bool            isEmpty(TreeTy* T) const { return !T; }
428f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  unsigned        getHeight(TreeTy* T) const { return T ? T->getHeight() : 0; }
429f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  TreeTy*         getLeft(TreeTy* T) const { return T->getLeft(); }
430f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  TreeTy*         getRight(TreeTy* T) const { return T->getRight(); }
431f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  value_type_ref  getValue(TreeTy* T) const { return T->value; }
432f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
433f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // Make sure the index is not the Tombstone or Entry key of the DenseMap.
434f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  static unsigned maskCacheIndex(unsigned I) { return (I & ~0x02); }
435f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
436f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  unsigned incrementHeight(TreeTy* L, TreeTy* R) const {
437f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    unsigned hl = getHeight(L);
438f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    unsigned hr = getHeight(R);
439f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return (hl > hr ? hl : hr) + 1;
440f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
441f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
442f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  static bool compareTreeWithSection(TreeTy* T,
443f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot                                     typename TreeTy::iterator& TI,
444f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot                                     typename TreeTy::iterator& TE) {
445f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    typename TreeTy::iterator I = T->begin(), E = T->end();
446f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    for ( ; I!=E ; ++I, ++TI) {
447f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      if (TI == TE || !I->isElementEqual(&*TI))
448f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        return false;
449f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    }
450f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return true;
451f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
452f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
453f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  //===--------------------------------------------------===//
454f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // "createNode" is used to generate new tree roots that link
455f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // to other trees.  The functon may also simply move links
456f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // in an existing root if that root is still marked mutable.
457f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // This is necessary because otherwise our balancing code
458f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // would leak memory as it would create nodes that are
459f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // then discarded later before the finished tree is
460f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // returned to the caller.
461f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  //===--------------------------------------------------===//
462f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
463f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  TreeTy* createNode(TreeTy* L, value_type_ref V, TreeTy* R) {
464f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    BumpPtrAllocator& A = getAllocator();
465f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    TreeTy* T;
466f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (!freeNodes.empty()) {
467f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      T = freeNodes.back();
468f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      freeNodes.pop_back();
469f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      assert(T != L);
470f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      assert(T != R);
471f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    } else {
472f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      T = (TreeTy*) A.Allocate<TreeTy>();
473f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    }
474f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    new (T) TreeTy(this, L, R, V, incrementHeight(L,R));
475f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    createdNodes.push_back(T);
476f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return T;
477f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
478f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
479f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  TreeTy* createNode(TreeTy* newLeft, TreeTy* oldTree, TreeTy* newRight) {
480f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return createNode(newLeft, getValue(oldTree), newRight);
481f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
482f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
483f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  void recoverNodes() {
484f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    for (unsigned i = 0, n = createdNodes.size(); i < n; ++i) {
485f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      TreeTy *N = createdNodes[i];
486f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      if (N->isMutable() && N->refCount == 0)
487f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        N->destroy();
488f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    }
489f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    createdNodes.clear();
490f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
491f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
492f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// balanceTree - Used by add_internal and remove_internal to
493f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///  balance a newly created tree.
494f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  TreeTy* balanceTree(TreeTy* L, value_type_ref V, TreeTy* R) {
495f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    unsigned hl = getHeight(L);
496f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    unsigned hr = getHeight(R);
497f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
498f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (hl > hr + 2) {
499f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      assert(!isEmpty(L) && "Left tree cannot be empty to have a height >= 2");
500f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
501f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      TreeTy *LL = getLeft(L);
502f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      TreeTy *LR = getRight(L);
503f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
504f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      if (getHeight(LL) >= getHeight(LR))
505f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        return createNode(LL, L, createNode(LR,V,R));
506f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
507f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      assert(!isEmpty(LR) && "LR cannot be empty because it has a height >= 1");
508f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
509f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      TreeTy *LRL = getLeft(LR);
510f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      TreeTy *LRR = getRight(LR);
511f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
512f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      return createNode(createNode(LL,L,LRL), LR, createNode(LRR,V,R));
513f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    }
514f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
515f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (hr > hl + 2) {
516f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      assert(!isEmpty(R) && "Right tree cannot be empty to have a height >= 2");
517f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
518f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      TreeTy *RL = getLeft(R);
519f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      TreeTy *RR = getRight(R);
520f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
521f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      if (getHeight(RR) >= getHeight(RL))
522f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        return createNode(createNode(L,V,RL), R, RR);
523f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
524f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      assert(!isEmpty(RL) && "RL cannot be empty because it has a height >= 1");
525f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
526f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      TreeTy *RLL = getLeft(RL);
527f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      TreeTy *RLR = getRight(RL);
528f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
529f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      return createNode(createNode(L,V,RLL), RL, createNode(RLR,R,RR));
530f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    }
531f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
532f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return createNode(L,V,R);
533f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
534f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
535f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// add_internal - Creates a new tree that includes the specified
536f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///  data and the data from the original tree.  If the original tree
537f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///  already contained the data item, the original tree is returned.
538f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  TreeTy* add_internal(value_type_ref V, TreeTy* T) {
539f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (isEmpty(T))
540f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      return createNode(T, V, T);
541f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    assert(!T->isMutable());
542f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
543f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    key_type_ref K = ImutInfo::KeyOfValue(V);
544f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    key_type_ref KCurrent = ImutInfo::KeyOfValue(getValue(T));
545f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
546f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (ImutInfo::isEqual(K,KCurrent))
547f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      return createNode(getLeft(T), V, getRight(T));
548f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    else if (ImutInfo::isLess(K,KCurrent))
549f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      return balanceTree(add_internal(V, getLeft(T)), getValue(T), getRight(T));
550f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    else
551f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      return balanceTree(getLeft(T), getValue(T), add_internal(V, getRight(T)));
552f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
553f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
554f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// remove_internal - Creates a new tree that includes all the data
555f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///  from the original tree except the specified data.  If the
556f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///  specified data did not exist in the original tree, the original
557f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///  tree is returned.
558f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  TreeTy* remove_internal(key_type_ref K, TreeTy* T) {
559f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (isEmpty(T))
560f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      return T;
561f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
562f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    assert(!T->isMutable());
563f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
564f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    key_type_ref KCurrent = ImutInfo::KeyOfValue(getValue(T));
565f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
566f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (ImutInfo::isEqual(K,KCurrent)) {
567f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      return combineTrees(getLeft(T), getRight(T));
568f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    } else if (ImutInfo::isLess(K,KCurrent)) {
569f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      return balanceTree(remove_internal(K, getLeft(T)),
570f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot                                            getValue(T), getRight(T));
571f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    } else {
572f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      return balanceTree(getLeft(T), getValue(T),
573f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot                         remove_internal(K, getRight(T)));
574f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    }
575f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
576f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
577f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  TreeTy* combineTrees(TreeTy* L, TreeTy* R) {
578f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (isEmpty(L))
579f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      return R;
580f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (isEmpty(R))
581f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      return L;
582f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    TreeTy* OldNode;
583f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    TreeTy* newRight = removeMinBinding(R,OldNode);
584f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return balanceTree(L, getValue(OldNode), newRight);
585f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
586f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
587f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  TreeTy* removeMinBinding(TreeTy* T, TreeTy*& Noderemoved) {
588f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    assert(!isEmpty(T));
589f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (isEmpty(getLeft(T))) {
590f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      Noderemoved = T;
591f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      return getRight(T);
592f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    }
593f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return balanceTree(removeMinBinding(getLeft(T), Noderemoved),
594f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot                       getValue(T), getRight(T));
595f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
596f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
597f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// markImmutable - Clears the mutable bits of a root and all of its
598f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///  descendants.
599f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  void markImmutable(TreeTy* T) {
600f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (!T || !T->isMutable())
601f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      return;
602f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    T->markImmutable();
603f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    markImmutable(getLeft(T));
604f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    markImmutable(getRight(T));
605f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
606f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
607f3014761c955345d6e05491608e73228d014afbandroid-build-team Robotpublic:
608f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  TreeTy *getCanonicalTree(TreeTy *TNew) {
609f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (!TNew)
610f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      return nullptr;
611f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
612f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (TNew->IsCanonicalized)
613f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      return TNew;
614f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
615f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    // Search the hashtable for another tree with the same digest, and
616f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    // if find a collision compare those trees by their contents.
617f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    unsigned digest = TNew->computeDigest();
618f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    TreeTy *&entry = Cache[maskCacheIndex(digest)];
619f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    do {
620f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      if (!entry)
621f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        break;
622f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      for (TreeTy *T = entry ; T != nullptr; T = T->next) {
623f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        // Compare the Contents('T') with Contents('TNew')
624f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        typename TreeTy::iterator TI = T->begin(), TE = T->end();
625f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        if (!compareTreeWithSection(TNew, TI, TE))
626f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot          continue;
627f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        if (TI != TE)
628f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot          continue; // T has more contents than TNew.
629f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        // Trees did match!  Return 'T'.
630f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        if (TNew->refCount == 0)
631f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot          TNew->destroy();
632f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        return T;
633f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      }
634f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      entry->prev = TNew;
635f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      TNew->next = entry;
636f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    }
637f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    while (false);
638f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
639f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    entry = TNew;
640f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    TNew->IsCanonicalized = true;
641f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return TNew;
642f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
643f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot};
644f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
645f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot//===----------------------------------------------------------------------===//
646f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot// Immutable AVL-Tree Iterators.
647f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot//===----------------------------------------------------------------------===//
648f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
649f3014761c955345d6e05491608e73228d014afbandroid-build-team Robottemplate <typename ImutInfo>
650f3014761c955345d6e05491608e73228d014afbandroid-build-team Robotclass ImutAVLTreeGenericIterator
651f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    : public std::iterator<std::bidirectional_iterator_tag,
652f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot                           ImutAVLTree<ImutInfo>> {
653f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  SmallVector<uintptr_t,20> stack;
654f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
655f3014761c955345d6e05491608e73228d014afbandroid-build-team Robotpublic:
656f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  enum VisitFlag { VisitedNone=0x0, VisitedLeft=0x1, VisitedRight=0x3,
657f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot                   Flags=0x3 };
658f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
659f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using TreeTy = ImutAVLTree<ImutInfo>;
660f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
661f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ImutAVLTreeGenericIterator() = default;
662f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ImutAVLTreeGenericIterator(const TreeTy *Root) {
663f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (Root) stack.push_back(reinterpret_cast<uintptr_t>(Root));
664f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
665f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
666f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  TreeTy &operator*() const {
667f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    assert(!stack.empty());
668f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return *reinterpret_cast<TreeTy *>(stack.back() & ~Flags);
669f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
670f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  TreeTy *operator->() const { return &*this; }
671f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
672f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  uintptr_t getVisitState() const {
673f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    assert(!stack.empty());
674f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return stack.back() & Flags;
675f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
676f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
677f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  bool atEnd() const { return stack.empty(); }
678f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
679f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  bool atBeginning() const {
680f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return stack.size() == 1 && getVisitState() == VisitedNone;
681f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
682f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
683f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  void skipToParent() {
684f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    assert(!stack.empty());
685f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    stack.pop_back();
686f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (stack.empty())
687f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      return;
688f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    switch (getVisitState()) {
689f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      case VisitedNone:
690f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        stack.back() |= VisitedLeft;
691f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        break;
692f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      case VisitedLeft:
693f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        stack.back() |= VisitedRight;
694f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        break;
695f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      default:
696f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        llvm_unreachable("Unreachable.");
697f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    }
698f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
699f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
700f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  bool operator==(const ImutAVLTreeGenericIterator &x) const {
701f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return stack == x.stack;
702f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
703f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
704f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  bool operator!=(const ImutAVLTreeGenericIterator &x) const {
705f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return !(*this == x);
706f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
707f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
708f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ImutAVLTreeGenericIterator &operator++() {
709f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    assert(!stack.empty());
710f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    TreeTy* Current = reinterpret_cast<TreeTy*>(stack.back() & ~Flags);
711f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    assert(Current);
712f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    switch (getVisitState()) {
713f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      case VisitedNone:
714f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        if (TreeTy* L = Current->getLeft())
715f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot          stack.push_back(reinterpret_cast<uintptr_t>(L));
716f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        else
717f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot          stack.back() |= VisitedLeft;
718f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        break;
719f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      case VisitedLeft:
720f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        if (TreeTy* R = Current->getRight())
721f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot          stack.push_back(reinterpret_cast<uintptr_t>(R));
722f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        else
723f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot          stack.back() |= VisitedRight;
724f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        break;
725f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      case VisitedRight:
726f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        skipToParent();
727f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        break;
728f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      default:
729f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        llvm_unreachable("Unreachable.");
730f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    }
731f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return *this;
732f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
733f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
734f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ImutAVLTreeGenericIterator &operator--() {
735f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    assert(!stack.empty());
736f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    TreeTy* Current = reinterpret_cast<TreeTy*>(stack.back() & ~Flags);
737f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    assert(Current);
738f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    switch (getVisitState()) {
739f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      case VisitedNone:
740f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        stack.pop_back();
741f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        break;
742f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      case VisitedLeft:
743f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        stack.back() &= ~Flags; // Set state to "VisitedNone."
744f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        if (TreeTy* L = Current->getLeft())
745f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot          stack.push_back(reinterpret_cast<uintptr_t>(L) | VisitedRight);
746f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        break;
747f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      case VisitedRight:
748f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        stack.back() &= ~Flags;
749f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        stack.back() |= VisitedLeft;
750f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        if (TreeTy* R = Current->getRight())
751f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot          stack.push_back(reinterpret_cast<uintptr_t>(R) | VisitedRight);
752f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        break;
753f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      default:
754f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        llvm_unreachable("Unreachable.");
755f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    }
756f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return *this;
757f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
758f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot};
759f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
760f3014761c955345d6e05491608e73228d014afbandroid-build-team Robottemplate <typename ImutInfo>
761f3014761c955345d6e05491608e73228d014afbandroid-build-team Robotclass ImutAVLTreeInOrderIterator
762f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    : public std::iterator<std::bidirectional_iterator_tag,
763f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot                           ImutAVLTree<ImutInfo>> {
764f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using InternalIteratorTy = ImutAVLTreeGenericIterator<ImutInfo>;
765f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
766f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  InternalIteratorTy InternalItr;
767f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
768f3014761c955345d6e05491608e73228d014afbandroid-build-team Robotpublic:
769f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using TreeTy = ImutAVLTree<ImutInfo>;
770f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
771f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ImutAVLTreeInOrderIterator(const TreeTy* Root) : InternalItr(Root) {
772f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (Root)
773f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      ++*this; // Advance to first element.
774f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
775f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
776f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ImutAVLTreeInOrderIterator() : InternalItr() {}
777f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
778f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  bool operator==(const ImutAVLTreeInOrderIterator &x) const {
779f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return InternalItr == x.InternalItr;
780f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
781f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
782f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  bool operator!=(const ImutAVLTreeInOrderIterator &x) const {
783f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return !(*this == x);
784f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
785f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
786f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  TreeTy &operator*() const { return *InternalItr; }
787f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  TreeTy *operator->() const { return &*InternalItr; }
788f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
789f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ImutAVLTreeInOrderIterator &operator++() {
790f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    do ++InternalItr;
791f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    while (!InternalItr.atEnd() &&
792f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot           InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft);
793f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
794f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return *this;
795f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
796f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
797f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ImutAVLTreeInOrderIterator &operator--() {
798f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    do --InternalItr;
799f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    while (!InternalItr.atBeginning() &&
800f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot           InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft);
801f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
802f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return *this;
803f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
804f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
805f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  void skipSubTree() {
806f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    InternalItr.skipToParent();
807f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
808f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    while (!InternalItr.atEnd() &&
809f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot           InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft)
810f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      ++InternalItr;
811f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
812f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot};
813f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
814f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot/// Generic iterator that wraps a T::TreeTy::iterator and exposes
815f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot/// iterator::getValue() on dereference.
816f3014761c955345d6e05491608e73228d014afbandroid-build-team Robottemplate <typename T>
817f3014761c955345d6e05491608e73228d014afbandroid-build-team Robotstruct ImutAVLValueIterator
818f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    : iterator_adaptor_base<
819f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot          ImutAVLValueIterator<T>, typename T::TreeTy::iterator,
820f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot          typename std::iterator_traits<
821f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot              typename T::TreeTy::iterator>::iterator_category,
822f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot          const typename T::value_type> {
823f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ImutAVLValueIterator() = default;
824f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  explicit ImutAVLValueIterator(typename T::TreeTy *Tree)
825f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      : ImutAVLValueIterator::iterator_adaptor_base(Tree) {}
826f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
827f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  typename ImutAVLValueIterator::reference operator*() const {
828f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return this->I->getValue();
829f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
830f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot};
831f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
832f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot//===----------------------------------------------------------------------===//
833f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot// Trait classes for Profile information.
834f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot//===----------------------------------------------------------------------===//
835f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
836f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot/// Generic profile template.  The default behavior is to invoke the
837f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot/// profile method of an object.  Specializations for primitive integers
838f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot/// and generic handling of pointers is done below.
839f3014761c955345d6e05491608e73228d014afbandroid-build-team Robottemplate <typename T>
840f3014761c955345d6e05491608e73228d014afbandroid-build-team Robotstruct ImutProfileInfo {
841f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using value_type = const T;
842f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using value_type_ref = const T&;
843f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
844f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  static void Profile(FoldingSetNodeID &ID, value_type_ref X) {
845f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    FoldingSetTrait<T>::Profile(X,ID);
846f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
847f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot};
848f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
849f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot/// Profile traits for integers.
850f3014761c955345d6e05491608e73228d014afbandroid-build-team Robottemplate <typename T>
851f3014761c955345d6e05491608e73228d014afbandroid-build-team Robotstruct ImutProfileInteger {
852f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using value_type = const T;
853f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using value_type_ref = const T&;
854f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
855f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  static void Profile(FoldingSetNodeID &ID, value_type_ref X) {
856f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    ID.AddInteger(X);
857f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
858f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot};
859f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
860f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot#define PROFILE_INTEGER_INFO(X)\
861f3014761c955345d6e05491608e73228d014afbandroid-build-team Robottemplate<> struct ImutProfileInfo<X> : ImutProfileInteger<X> {};
862f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
863f3014761c955345d6e05491608e73228d014afbandroid-build-team RobotPROFILE_INTEGER_INFO(char)
864f3014761c955345d6e05491608e73228d014afbandroid-build-team RobotPROFILE_INTEGER_INFO(unsigned char)
865f3014761c955345d6e05491608e73228d014afbandroid-build-team RobotPROFILE_INTEGER_INFO(short)
866f3014761c955345d6e05491608e73228d014afbandroid-build-team RobotPROFILE_INTEGER_INFO(unsigned short)
867f3014761c955345d6e05491608e73228d014afbandroid-build-team RobotPROFILE_INTEGER_INFO(unsigned)
868f3014761c955345d6e05491608e73228d014afbandroid-build-team RobotPROFILE_INTEGER_INFO(signed)
869f3014761c955345d6e05491608e73228d014afbandroid-build-team RobotPROFILE_INTEGER_INFO(long)
870f3014761c955345d6e05491608e73228d014afbandroid-build-team RobotPROFILE_INTEGER_INFO(unsigned long)
871f3014761c955345d6e05491608e73228d014afbandroid-build-team RobotPROFILE_INTEGER_INFO(long long)
872f3014761c955345d6e05491608e73228d014afbandroid-build-team RobotPROFILE_INTEGER_INFO(unsigned long long)
873f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
874f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot#undef PROFILE_INTEGER_INFO
875f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
876f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot/// Profile traits for booleans.
877f3014761c955345d6e05491608e73228d014afbandroid-build-team Robottemplate <>
878f3014761c955345d6e05491608e73228d014afbandroid-build-team Robotstruct ImutProfileInfo<bool> {
879f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using value_type = const bool;
880f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using value_type_ref = const bool&;
881f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
882f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  static void Profile(FoldingSetNodeID &ID, value_type_ref X) {
883f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    ID.AddBoolean(X);
884f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
885f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot};
886f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
887f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot/// Generic profile trait for pointer types.  We treat pointers as
888f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot/// references to unique objects.
889f3014761c955345d6e05491608e73228d014afbandroid-build-team Robottemplate <typename T>
890f3014761c955345d6e05491608e73228d014afbandroid-build-team Robotstruct ImutProfileInfo<T*> {
891f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using value_type = const T*;
892f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using value_type_ref = value_type;
893f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
894f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  static void Profile(FoldingSetNodeID &ID, value_type_ref X) {
895f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    ID.AddPointer(X);
896f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
897f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot};
898f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
899f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot//===----------------------------------------------------------------------===//
900f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot// Trait classes that contain element comparison operators and type
901f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot//  definitions used by ImutAVLTree, ImmutableSet, and ImmutableMap.  These
902f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot//  inherit from the profile traits (ImutProfileInfo) to include operations
903f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot//  for element profiling.
904f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot//===----------------------------------------------------------------------===//
905f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
906f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot/// ImutContainerInfo - Generic definition of comparison operations for
907f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot///   elements of immutable containers that defaults to using
908f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot///   std::equal_to<> and std::less<> to perform comparison of elements.
909f3014761c955345d6e05491608e73228d014afbandroid-build-team Robottemplate <typename T>
910f3014761c955345d6e05491608e73228d014afbandroid-build-team Robotstruct ImutContainerInfo : public ImutProfileInfo<T> {
911f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using value_type = typename ImutProfileInfo<T>::value_type;
912f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using value_type_ref = typename ImutProfileInfo<T>::value_type_ref;
913f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using key_type = value_type;
914f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using key_type_ref = value_type_ref;
915f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using data_type = bool;
916f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using data_type_ref = bool;
917f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
918f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  static key_type_ref KeyOfValue(value_type_ref D) { return D; }
919f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  static data_type_ref DataOfValue(value_type_ref) { return true; }
920f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
921f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  static bool isEqual(key_type_ref LHS, key_type_ref RHS) {
922f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return std::equal_to<key_type>()(LHS,RHS);
923f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
924f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
925f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  static bool isLess(key_type_ref LHS, key_type_ref RHS) {
926f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return std::less<key_type>()(LHS,RHS);
927f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
928f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
929f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  static bool isDataEqual(data_type_ref, data_type_ref) { return true; }
930f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot};
931f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
932f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot/// ImutContainerInfo - Specialization for pointer values to treat pointers
933f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot///  as references to unique objects.  Pointers are thus compared by
934f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot///  their addresses.
935f3014761c955345d6e05491608e73228d014afbandroid-build-team Robottemplate <typename T>
936f3014761c955345d6e05491608e73228d014afbandroid-build-team Robotstruct ImutContainerInfo<T*> : public ImutProfileInfo<T*> {
937f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using value_type = typename ImutProfileInfo<T*>::value_type;
938f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using value_type_ref = typename ImutProfileInfo<T*>::value_type_ref;
939f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using key_type = value_type;
940f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using key_type_ref = value_type_ref;
941f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using data_type = bool;
942f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using data_type_ref = bool;
943f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
944f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  static key_type_ref KeyOfValue(value_type_ref D) { return D; }
945f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  static data_type_ref DataOfValue(value_type_ref) { return true; }
946f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
947f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  static bool isEqual(key_type_ref LHS, key_type_ref RHS) { return LHS == RHS; }
948f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
949f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  static bool isLess(key_type_ref LHS, key_type_ref RHS) { return LHS < RHS; }
950f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
951f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  static bool isDataEqual(data_type_ref, data_type_ref) { return true; }
952f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot};
953f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
954f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot//===----------------------------------------------------------------------===//
955f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot// Immutable Set
956f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot//===----------------------------------------------------------------------===//
957f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
958f3014761c955345d6e05491608e73228d014afbandroid-build-team Robottemplate <typename ValT, typename ValInfo = ImutContainerInfo<ValT>>
959f3014761c955345d6e05491608e73228d014afbandroid-build-team Robotclass ImmutableSet {
960f3014761c955345d6e05491608e73228d014afbandroid-build-team Robotpublic:
961f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using value_type = typename ValInfo::value_type;
962f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using value_type_ref = typename ValInfo::value_type_ref;
963f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using TreeTy = ImutAVLTree<ValInfo>;
964f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
965f3014761c955345d6e05491608e73228d014afbandroid-build-team Robotprivate:
966f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  TreeTy *Root;
967f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
968f3014761c955345d6e05491608e73228d014afbandroid-build-team Robotpublic:
969f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// Constructs a set from a pointer to a tree root.  In general one
970f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// should use a Factory object to create sets instead of directly
971f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// invoking the constructor, but there are cases where make this
972f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// constructor public is useful.
973f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  explicit ImmutableSet(TreeTy* R) : Root(R) {
974f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (Root) { Root->retain(); }
975f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
976f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
977f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ImmutableSet(const ImmutableSet &X) : Root(X.Root) {
978f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (Root) { Root->retain(); }
979f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
980f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
981f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ~ImmutableSet() {
982f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (Root) { Root->release(); }
983f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
984f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
985f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ImmutableSet &operator=(const ImmutableSet &X) {
986f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (Root != X.Root) {
987f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      if (X.Root) { X.Root->retain(); }
988f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      if (Root) { Root->release(); }
989f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      Root = X.Root;
990f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    }
991f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return *this;
992f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
993f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
994f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  class Factory {
995f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    typename TreeTy::Factory F;
996f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    const bool Canonicalize;
997f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
998f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  public:
999f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    Factory(bool canonicalize = true)
1000f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      : Canonicalize(canonicalize) {}
1001f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1002f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    Factory(BumpPtrAllocator& Alloc, bool canonicalize = true)
1003f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      : F(Alloc), Canonicalize(canonicalize) {}
1004f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1005f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    Factory(const Factory& RHS) = delete;
1006f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    void operator=(const Factory& RHS) = delete;
1007f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1008f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    /// getEmptySet - Returns an immutable set that contains no elements.
1009f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    ImmutableSet getEmptySet() {
1010f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      return ImmutableSet(F.getEmptyTree());
1011f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    }
1012f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1013f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    /// add - Creates a new immutable set that contains all of the values
1014f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    ///  of the original set with the addition of the specified value.  If
1015f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    ///  the original set already included the value, then the original set is
1016f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    ///  returned and no memory is allocated.  The time and space complexity
1017f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    ///  of this operation is logarithmic in the size of the original set.
1018f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    ///  The memory allocated to represent the set is released when the
1019f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    ///  factory object that created the set is destroyed.
1020f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    ImmutableSet add(ImmutableSet Old, value_type_ref V) {
1021f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      TreeTy *NewT = F.add(Old.Root, V);
1022f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      return ImmutableSet(Canonicalize ? F.getCanonicalTree(NewT) : NewT);
1023f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    }
1024f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1025f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    /// remove - Creates a new immutable set that contains all of the values
1026f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    ///  of the original set with the exception of the specified value.  If
1027f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    ///  the original set did not contain the value, the original set is
1028f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    ///  returned and no memory is allocated.  The time and space complexity
1029f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    ///  of this operation is logarithmic in the size of the original set.
1030f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    ///  The memory allocated to represent the set is released when the
1031f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    ///  factory object that created the set is destroyed.
1032f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    ImmutableSet remove(ImmutableSet Old, value_type_ref V) {
1033f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      TreeTy *NewT = F.remove(Old.Root, V);
1034f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      return ImmutableSet(Canonicalize ? F.getCanonicalTree(NewT) : NewT);
1035f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    }
1036f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1037f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    BumpPtrAllocator& getAllocator() { return F.getAllocator(); }
1038f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1039f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    typename TreeTy::Factory *getTreeFactory() const {
1040f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      return const_cast<typename TreeTy::Factory *>(&F);
1041f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    }
1042f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  };
1043f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1044f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  friend class Factory;
1045f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1046f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// Returns true if the set contains the specified value.
1047f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  bool contains(value_type_ref V) const {
1048f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return Root ? Root->contains(V) : false;
1049f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
1050f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1051f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  bool operator==(const ImmutableSet &RHS) const {
1052f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root;
1053f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
1054f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1055f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  bool operator!=(const ImmutableSet &RHS) const {
1056f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root;
1057f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
1058f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1059f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  TreeTy *getRoot() {
1060f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (Root) { Root->retain(); }
1061f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return Root;
1062f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
1063f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1064f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  TreeTy *getRootWithoutRetain() const {
1065f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return Root;
1066f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
1067f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1068f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// isEmpty - Return true if the set contains no elements.
1069f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  bool isEmpty() const { return !Root; }
1070f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1071f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// isSingleton - Return true if the set contains exactly one element.
1072f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///   This method runs in constant time.
1073f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  bool isSingleton() const { return getHeight() == 1; }
1074f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1075f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  template <typename Callback>
1076f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  void foreach(Callback& C) { if (Root) Root->foreach(C); }
1077f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1078f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  template <typename Callback>
1079f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  void foreach() { if (Root) { Callback C; Root->foreach(C); } }
1080f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1081f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  //===--------------------------------------------------===//
1082f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // Iterators.
1083f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  //===--------------------------------------------------===//
1084f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1085f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using iterator = ImutAVLValueIterator<ImmutableSet>;
1086f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1087f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  iterator begin() const { return iterator(Root); }
1088f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  iterator end() const { return iterator(); }
1089f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1090f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  //===--------------------------------------------------===//
1091f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // Utility methods.
1092f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  //===--------------------------------------------------===//
1093f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1094f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  unsigned getHeight() const { return Root ? Root->getHeight() : 0; }
1095f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1096f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  static void Profile(FoldingSetNodeID &ID, const ImmutableSet &S) {
1097f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    ID.AddPointer(S.Root);
1098f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
1099f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1100f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  void Profile(FoldingSetNodeID &ID) const { return Profile(ID, *this); }
1101f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1102f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  //===--------------------------------------------------===//
1103f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // For testing.
1104f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  //===--------------------------------------------------===//
1105f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1106f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  void validateTree() const { if (Root) Root->validateTree(); }
1107f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot};
1108f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1109f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot// NOTE: This may some day replace the current ImmutableSet.
1110f3014761c955345d6e05491608e73228d014afbandroid-build-team Robottemplate <typename ValT, typename ValInfo = ImutContainerInfo<ValT>>
1111f3014761c955345d6e05491608e73228d014afbandroid-build-team Robotclass ImmutableSetRef {
1112f3014761c955345d6e05491608e73228d014afbandroid-build-team Robotpublic:
1113f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using value_type = typename ValInfo::value_type;
1114f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using value_type_ref = typename ValInfo::value_type_ref;
1115f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using TreeTy = ImutAVLTree<ValInfo>;
1116f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using FactoryTy = typename TreeTy::Factory;
1117f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1118f3014761c955345d6e05491608e73228d014afbandroid-build-team Robotprivate:
1119f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  TreeTy *Root;
1120f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  FactoryTy *Factory;
1121f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1122f3014761c955345d6e05491608e73228d014afbandroid-build-team Robotpublic:
1123f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// Constructs a set from a pointer to a tree root.  In general one
1124f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// should use a Factory object to create sets instead of directly
1125f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// invoking the constructor, but there are cases where make this
1126f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// constructor public is useful.
1127f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  explicit ImmutableSetRef(TreeTy* R, FactoryTy *F)
1128f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    : Root(R),
1129f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      Factory(F) {
1130f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (Root) { Root->retain(); }
1131f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
1132f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1133f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ImmutableSetRef(const ImmutableSetRef &X)
1134f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    : Root(X.Root),
1135f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      Factory(X.Factory) {
1136f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (Root) { Root->retain(); }
1137f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
1138f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1139f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ~ImmutableSetRef() {
1140f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (Root) { Root->release(); }
1141f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
1142f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1143f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ImmutableSetRef &operator=(const ImmutableSetRef &X) {
1144f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (Root != X.Root) {
1145f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      if (X.Root) { X.Root->retain(); }
1146f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      if (Root) { Root->release(); }
1147f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      Root = X.Root;
1148f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      Factory = X.Factory;
1149f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    }
1150f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return *this;
1151f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
1152f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1153f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  static ImmutableSetRef getEmptySet(FactoryTy *F) {
1154f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return ImmutableSetRef(0, F);
1155f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
1156f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1157f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ImmutableSetRef add(value_type_ref V) {
1158f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return ImmutableSetRef(Factory->add(Root, V), Factory);
1159f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
1160f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1161f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ImmutableSetRef remove(value_type_ref V) {
1162f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return ImmutableSetRef(Factory->remove(Root, V), Factory);
1163f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
1164f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1165f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// Returns true if the set contains the specified value.
1166f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  bool contains(value_type_ref V) const {
1167f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return Root ? Root->contains(V) : false;
1168f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
1169f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1170f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ImmutableSet<ValT> asImmutableSet(bool canonicalize = true) const {
1171f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return ImmutableSet<ValT>(canonicalize ?
1172f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot                              Factory->getCanonicalTree(Root) : Root);
1173f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
1174f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1175f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  TreeTy *getRootWithoutRetain() const {
1176f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return Root;
1177f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
1178f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1179f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  bool operator==(const ImmutableSetRef &RHS) const {
1180f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root;
1181f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
1182f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1183f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  bool operator!=(const ImmutableSetRef &RHS) const {
1184f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root;
1185f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
1186f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1187f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// isEmpty - Return true if the set contains no elements.
1188f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  bool isEmpty() const { return !Root; }
1189f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1190f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// isSingleton - Return true if the set contains exactly one element.
1191f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ///   This method runs in constant time.
1192f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  bool isSingleton() const { return getHeight() == 1; }
1193f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1194f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  //===--------------------------------------------------===//
1195f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // Iterators.
1196f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  //===--------------------------------------------------===//
1197f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1198f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  using iterator = ImutAVLValueIterator<ImmutableSetRef>;
1199f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1200f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  iterator begin() const { return iterator(Root); }
1201f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  iterator end() const { return iterator(); }
1202f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1203f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  //===--------------------------------------------------===//
1204f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // Utility methods.
1205f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  //===--------------------------------------------------===//
1206f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1207f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  unsigned getHeight() const { return Root ? Root->getHeight() : 0; }
1208f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1209f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  static void Profile(FoldingSetNodeID &ID, const ImmutableSetRef &S) {
1210f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    ID.AddPointer(S.Root);
1211f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
1212f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1213f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  void Profile(FoldingSetNodeID &ID) const { return Profile(ID, *this); }
1214f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1215f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  //===--------------------------------------------------===//
1216f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // For testing.
1217f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  //===--------------------------------------------------===//
1218f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1219f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  void validateTree() const { if (Root) Root->validateTree(); }
1220f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot};
1221f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1222f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot} // end namespace llvm
1223f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
1224f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot#endif // LLVM_ADT_IMMUTABLESET_H
1225