xref: /llvm-project/clang-tools-extra/clangd/index/dex/Iterator.cpp (revision c8f4792510f40bdf614f904f45e93eae8e306ddb)
1a522c1cfSKirill Bobyrev //===--- Iterator.cpp - Query Symbol Retrieval ------------------*- C++ -*-===//
2a522c1cfSKirill Bobyrev //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a522c1cfSKirill Bobyrev //
7a522c1cfSKirill Bobyrev //===----------------------------------------------------------------------===//
8a522c1cfSKirill Bobyrev 
9a522c1cfSKirill Bobyrev #include "Iterator.h"
104d006520SSam McCall #include "llvm/ADT/STLExtras.h"
11a522c1cfSKirill Bobyrev #include <algorithm>
12a522c1cfSKirill Bobyrev #include <cassert>
13a522c1cfSKirill Bobyrev #include <numeric>
14a522c1cfSKirill Bobyrev 
15a522c1cfSKirill Bobyrev namespace clang {
16a522c1cfSKirill Bobyrev namespace clangd {
17a522c1cfSKirill Bobyrev namespace dex {
18a522c1cfSKirill Bobyrev namespace {
19a522c1cfSKirill Bobyrev 
20a522c1cfSKirill Bobyrev /// Implements Iterator over the intersection of other iterators.
21a522c1cfSKirill Bobyrev ///
22a522c1cfSKirill Bobyrev /// AndIterator iterates through common items among all children. It becomes
23a522c1cfSKirill Bobyrev /// exhausted as soon as any child becomes exhausted. After each mutation, the
24a522c1cfSKirill Bobyrev /// iterator restores the invariant: all children must point to the same item.
25a522c1cfSKirill Bobyrev class AndIterator : public Iterator {
26a522c1cfSKirill Bobyrev public:
AndIterator(std::vector<std::unique_ptr<Iterator>> AllChildren)27e4ee0213SKirill Bobyrev   explicit AndIterator(std::vector<std::unique_ptr<Iterator>> AllChildren)
2887f69eafSSam McCall       : Iterator(Kind::And), Children(std::move(AllChildren)) {
29493b1627SKirill Bobyrev     assert(!Children.empty() && "AND iterator should have at least one child.");
30a522c1cfSKirill Bobyrev     // Establish invariants.
3187f69eafSSam McCall     for (const auto &Child : Children)
3287f69eafSSam McCall       ReachedEnd |= Child->reachedEnd();
33a522c1cfSKirill Bobyrev     sync();
3438bdac5dSKirill Bobyrev     // When children are sorted by the estimateSize(), sync() calls are more
3538bdac5dSKirill Bobyrev     // effective. Each sync() starts with the first child and makes sure all
3638bdac5dSKirill Bobyrev     // children point to the same element. If any child is "above" the previous
37*c8f47925SRageking8     // ones, the algorithm resets and advances the children to the next
3838bdac5dSKirill Bobyrev     // highest element starting from the front. When child iterators in the
3938bdac5dSKirill Bobyrev     // beginning have smaller estimated size, the sync() will have less restarts
4038bdac5dSKirill Bobyrev     // and become more effective.
414a5ff88fSKirill Bobyrev     llvm::sort(Children, [](const std::unique_ptr<Iterator> &LHS,
4238bdac5dSKirill Bobyrev                             const std::unique_ptr<Iterator> &RHS) {
4338bdac5dSKirill Bobyrev       return LHS->estimateSize() < RHS->estimateSize();
4438bdac5dSKirill Bobyrev     });
45a522c1cfSKirill Bobyrev   }
46a522c1cfSKirill Bobyrev 
reachedEnd() const47a522c1cfSKirill Bobyrev   bool reachedEnd() const override { return ReachedEnd; }
48a522c1cfSKirill Bobyrev 
49a522c1cfSKirill Bobyrev   /// Advances all children to the next common item.
advance()50a522c1cfSKirill Bobyrev   void advance() override {
51493b1627SKirill Bobyrev     assert(!reachedEnd() && "AND iterator can't advance() at the end.");
52a522c1cfSKirill Bobyrev     Children.front()->advance();
53a522c1cfSKirill Bobyrev     sync();
54a522c1cfSKirill Bobyrev   }
55a522c1cfSKirill Bobyrev 
56a522c1cfSKirill Bobyrev   /// Advances all children to the next common item with DocumentID >= ID.
advanceTo(DocID ID)57a522c1cfSKirill Bobyrev   void advanceTo(DocID ID) override {
58493b1627SKirill Bobyrev     assert(!reachedEnd() && "AND iterator can't advanceTo() at the end.");
59a522c1cfSKirill Bobyrev     Children.front()->advanceTo(ID);
60a522c1cfSKirill Bobyrev     sync();
61a522c1cfSKirill Bobyrev   }
62a522c1cfSKirill Bobyrev 
peek() const63a522c1cfSKirill Bobyrev   DocID peek() const override { return Children.front()->peek(); }
64a522c1cfSKirill Bobyrev 
consume()65a98961bcSKirill Bobyrev   float consume() override {
66493b1627SKirill Bobyrev     assert(!reachedEnd() && "AND iterator can't consume() at the end.");
67a659d779SSam McCall     float Boost = 1;
68d041f8a9SKirill Bobyrev     for (const auto &Child : Children)
69d041f8a9SKirill Bobyrev       Boost *= Child->consume();
70d041f8a9SKirill Bobyrev     return Boost;
717413e985SKirill Bobyrev   }
727413e985SKirill Bobyrev 
estimateSize() const7338bdac5dSKirill Bobyrev   size_t estimateSize() const override {
7438bdac5dSKirill Bobyrev     return Children.front()->estimateSize();
7538bdac5dSKirill Bobyrev   }
7638bdac5dSKirill Bobyrev 
776d8bd7f5SKirill Bobyrev private:
dump(llvm::raw_ostream & OS) const78f2001aa7SIlya Biryukov   llvm::raw_ostream &dump(llvm::raw_ostream &OS) const override {
79a522c1cfSKirill Bobyrev     OS << "(& ";
80c0e3c893SChristian Kühnel     auto *Separator = "";
81a522c1cfSKirill Bobyrev     for (const auto &Child : Children) {
82a522c1cfSKirill Bobyrev       OS << Separator << *Child;
83a522c1cfSKirill Bobyrev       Separator = " ";
84a522c1cfSKirill Bobyrev     }
85a522c1cfSKirill Bobyrev     OS << ')';
86a522c1cfSKirill Bobyrev     return OS;
87a522c1cfSKirill Bobyrev   }
88a522c1cfSKirill Bobyrev 
89a522c1cfSKirill Bobyrev   /// Restores class invariants: each child will point to the same element after
90a522c1cfSKirill Bobyrev   /// sync.
sync()91a522c1cfSKirill Bobyrev   void sync() {
92a522c1cfSKirill Bobyrev     ReachedEnd |= Children.front()->reachedEnd();
93a522c1cfSKirill Bobyrev     if (ReachedEnd)
94a522c1cfSKirill Bobyrev       return;
95a522c1cfSKirill Bobyrev     auto SyncID = Children.front()->peek();
96a522c1cfSKirill Bobyrev     // Indicates whether any child needs to be advanced to new SyncID.
97a522c1cfSKirill Bobyrev     bool NeedsAdvance = false;
98a522c1cfSKirill Bobyrev     do {
99a522c1cfSKirill Bobyrev       NeedsAdvance = false;
100a522c1cfSKirill Bobyrev       for (auto &Child : Children) {
101a522c1cfSKirill Bobyrev         Child->advanceTo(SyncID);
102a522c1cfSKirill Bobyrev         ReachedEnd |= Child->reachedEnd();
103a522c1cfSKirill Bobyrev         // If any child reaches end And iterator can not match any other items.
104a522c1cfSKirill Bobyrev         // In this case, just terminate the process.
105a522c1cfSKirill Bobyrev         if (ReachedEnd)
106a522c1cfSKirill Bobyrev           return;
107a0987e35SKirill Bobyrev         // Cache the result so that peek() is not called again as it may be
108a0987e35SKirill Bobyrev         // quite expensive in AND with large subtrees.
109a0987e35SKirill Bobyrev         auto Candidate = Child->peek();
110a522c1cfSKirill Bobyrev         // If any child goes beyond given ID (i.e. ID is not the common item),
111a522c1cfSKirill Bobyrev         // all children should be advanced to the next common item.
112a0987e35SKirill Bobyrev         if (Candidate > SyncID) {
113a0987e35SKirill Bobyrev           SyncID = Candidate;
114a522c1cfSKirill Bobyrev           NeedsAdvance = true;
115a0987e35SKirill Bobyrev           // Reset and try to sync again. Sync starts with the first child as
116a0987e35SKirill Bobyrev           // this is the cheapest (smallest size estimate). This way advanceTo
117a0987e35SKirill Bobyrev           // is called on the large posting lists once the sync point is very
118a0987e35SKirill Bobyrev           // likely.
119a0987e35SKirill Bobyrev           break;
120a522c1cfSKirill Bobyrev         }
121a522c1cfSKirill Bobyrev       }
122a522c1cfSKirill Bobyrev     } while (NeedsAdvance);
123a522c1cfSKirill Bobyrev   }
124a522c1cfSKirill Bobyrev 
125a522c1cfSKirill Bobyrev   /// AndIterator owns its children and ensures that all of them point to the
126a522c1cfSKirill Bobyrev   /// same element. As soon as one child gets exhausted, AndIterator can no
127a522c1cfSKirill Bobyrev   /// longer advance and has reached its end.
128a522c1cfSKirill Bobyrev   std::vector<std::unique_ptr<Iterator>> Children;
129a522c1cfSKirill Bobyrev   /// Indicates whether any child is exhausted. It is cheaper to maintain and
130a522c1cfSKirill Bobyrev   /// update the field, rather than traversing the whole subtree in each
131a522c1cfSKirill Bobyrev   /// reachedEnd() call.
132a522c1cfSKirill Bobyrev   bool ReachedEnd = false;
13387f69eafSSam McCall   friend Corpus; // For optimizations.
134a522c1cfSKirill Bobyrev };
135a522c1cfSKirill Bobyrev 
136a522c1cfSKirill Bobyrev /// Implements Iterator over the union of other iterators.
137a522c1cfSKirill Bobyrev ///
138a522c1cfSKirill Bobyrev /// OrIterator iterates through all items which can be pointed to by at least
139a522c1cfSKirill Bobyrev /// one child. To preserve the sorted order, this iterator always advances the
140a522c1cfSKirill Bobyrev /// child with smallest Child->peek() value. OrIterator becomes exhausted as
141a522c1cfSKirill Bobyrev /// soon as all of its children are exhausted.
142a522c1cfSKirill Bobyrev class OrIterator : public Iterator {
143a522c1cfSKirill Bobyrev public:
OrIterator(std::vector<std::unique_ptr<Iterator>> AllChildren)144e4ee0213SKirill Bobyrev   explicit OrIterator(std::vector<std::unique_ptr<Iterator>> AllChildren)
14587f69eafSSam McCall       : Iterator(Kind::Or), Children(std::move(AllChildren)) {
146d9f33b12SKirill Bobyrev     assert(!Children.empty() && "OR iterator should have at least one child.");
147a522c1cfSKirill Bobyrev   }
148a522c1cfSKirill Bobyrev 
149a522c1cfSKirill Bobyrev   /// Returns true if all children are exhausted.
reachedEnd() const150a522c1cfSKirill Bobyrev   bool reachedEnd() const override {
151d041f8a9SKirill Bobyrev     for (const auto &Child : Children)
152d041f8a9SKirill Bobyrev       if (!Child->reachedEnd())
153d041f8a9SKirill Bobyrev         return false;
154d041f8a9SKirill Bobyrev     return true;
155a522c1cfSKirill Bobyrev   }
156a522c1cfSKirill Bobyrev 
157a522c1cfSKirill Bobyrev   /// Moves each child pointing to the smallest DocID to the next item.
advance()158a522c1cfSKirill Bobyrev   void advance() override {
159493b1627SKirill Bobyrev     assert(!reachedEnd() && "OR iterator can't advance() at the end.");
160a522c1cfSKirill Bobyrev     const auto SmallestID = peek();
161a522c1cfSKirill Bobyrev     for (const auto &Child : Children)
162a522c1cfSKirill Bobyrev       if (!Child->reachedEnd() && Child->peek() == SmallestID)
163a522c1cfSKirill Bobyrev         Child->advance();
164a522c1cfSKirill Bobyrev   }
165a522c1cfSKirill Bobyrev 
166a522c1cfSKirill Bobyrev   /// Advances each child to the next existing element with DocumentID >= ID.
advanceTo(DocID ID)167a522c1cfSKirill Bobyrev   void advanceTo(DocID ID) override {
168493b1627SKirill Bobyrev     assert(!reachedEnd() && "OR iterator can't advanceTo() at the end.");
169a522c1cfSKirill Bobyrev     for (const auto &Child : Children)
170a522c1cfSKirill Bobyrev       if (!Child->reachedEnd())
171a522c1cfSKirill Bobyrev         Child->advanceTo(ID);
172a522c1cfSKirill Bobyrev   }
173a522c1cfSKirill Bobyrev 
174a522c1cfSKirill Bobyrev   /// Returns the element under cursor of the child with smallest Child->peek()
175a522c1cfSKirill Bobyrev   /// value.
peek() const176a522c1cfSKirill Bobyrev   DocID peek() const override {
177493b1627SKirill Bobyrev     assert(!reachedEnd() && "OR iterator can't peek() at the end.");
178a522c1cfSKirill Bobyrev     DocID Result = std::numeric_limits<DocID>::max();
179a522c1cfSKirill Bobyrev 
180a522c1cfSKirill Bobyrev     for (const auto &Child : Children)
181a522c1cfSKirill Bobyrev       if (!Child->reachedEnd())
182a522c1cfSKirill Bobyrev         Result = std::min(Result, Child->peek());
183a522c1cfSKirill Bobyrev 
184a522c1cfSKirill Bobyrev     return Result;
185a522c1cfSKirill Bobyrev   }
186a522c1cfSKirill Bobyrev 
187a659d779SSam McCall   // Returns the maximum boosting score among all Children when iterator
188a659d779SSam McCall   // points to the current ID.
consume()189a98961bcSKirill Bobyrev   float consume() override {
190493b1627SKirill Bobyrev     assert(!reachedEnd() && "OR iterator can't consume() at the end.");
191a98961bcSKirill Bobyrev     const DocID ID = peek();
192a659d779SSam McCall     float Boost = 1;
193d041f8a9SKirill Bobyrev     for (const auto &Child : Children)
194d041f8a9SKirill Bobyrev       if (!Child->reachedEnd() && Child->peek() == ID)
195d041f8a9SKirill Bobyrev         Boost = std::max(Boost, Child->consume());
196d041f8a9SKirill Bobyrev     return Boost;
1977413e985SKirill Bobyrev   }
1987413e985SKirill Bobyrev 
estimateSize() const19938bdac5dSKirill Bobyrev   size_t estimateSize() const override {
200d041f8a9SKirill Bobyrev     size_t Size = 0;
201d041f8a9SKirill Bobyrev     for (const auto &Child : Children)
202d041f8a9SKirill Bobyrev       Size = std::max(Size, Child->estimateSize());
203d041f8a9SKirill Bobyrev     return Size;
20438bdac5dSKirill Bobyrev   }
20538bdac5dSKirill Bobyrev 
2066d8bd7f5SKirill Bobyrev private:
dump(llvm::raw_ostream & OS) const207f2001aa7SIlya Biryukov   llvm::raw_ostream &dump(llvm::raw_ostream &OS) const override {
208a522c1cfSKirill Bobyrev     OS << "(| ";
209c0e3c893SChristian Kühnel     auto *Separator = "";
210a522c1cfSKirill Bobyrev     for (const auto &Child : Children) {
211a522c1cfSKirill Bobyrev       OS << Separator << *Child;
212a522c1cfSKirill Bobyrev       Separator = " ";
213a522c1cfSKirill Bobyrev     }
214a522c1cfSKirill Bobyrev     OS << ')';
215a522c1cfSKirill Bobyrev     return OS;
216a522c1cfSKirill Bobyrev   }
217a522c1cfSKirill Bobyrev 
218a522c1cfSKirill Bobyrev   std::vector<std::unique_ptr<Iterator>> Children;
21987f69eafSSam McCall   friend Corpus; // For optimizations.
220a522c1cfSKirill Bobyrev };
221a522c1cfSKirill Bobyrev 
22230ffdf42SKirill Bobyrev /// TrueIterator handles PostingLists which contain all items of the index. It
22330ffdf42SKirill Bobyrev /// stores size of the virtual posting list, and all operations are performed
22430ffdf42SKirill Bobyrev /// in O(1).
22530ffdf42SKirill Bobyrev class TrueIterator : public Iterator {
22630ffdf42SKirill Bobyrev public:
TrueIterator(DocID Size)22787f69eafSSam McCall   explicit TrueIterator(DocID Size) : Iterator(Kind::True), Size(Size) {}
22830ffdf42SKirill Bobyrev 
reachedEnd() const22930ffdf42SKirill Bobyrev   bool reachedEnd() const override { return Index >= Size; }
23030ffdf42SKirill Bobyrev 
advance()23130ffdf42SKirill Bobyrev   void advance() override {
232493b1627SKirill Bobyrev     assert(!reachedEnd() && "TRUE iterator can't advance() at the end.");
23330ffdf42SKirill Bobyrev     ++Index;
23430ffdf42SKirill Bobyrev   }
23530ffdf42SKirill Bobyrev 
advanceTo(DocID ID)23630ffdf42SKirill Bobyrev   void advanceTo(DocID ID) override {
237493b1627SKirill Bobyrev     assert(!reachedEnd() && "TRUE iterator can't advanceTo() at the end.");
23830ffdf42SKirill Bobyrev     Index = std::min(ID, Size);
23930ffdf42SKirill Bobyrev   }
24030ffdf42SKirill Bobyrev 
peek() const24130ffdf42SKirill Bobyrev   DocID peek() const override {
242493b1627SKirill Bobyrev     assert(!reachedEnd() && "TRUE iterator can't peek() at the end.");
24330ffdf42SKirill Bobyrev     return Index;
24430ffdf42SKirill Bobyrev   }
24530ffdf42SKirill Bobyrev 
consume()246493b1627SKirill Bobyrev   float consume() override {
247493b1627SKirill Bobyrev     assert(!reachedEnd() && "TRUE iterator can't consume() at the end.");
248a659d779SSam McCall     return 1;
249493b1627SKirill Bobyrev   }
2507413e985SKirill Bobyrev 
estimateSize() const25138bdac5dSKirill Bobyrev   size_t estimateSize() const override { return Size; }
25238bdac5dSKirill Bobyrev 
25330ffdf42SKirill Bobyrev private:
dump(llvm::raw_ostream & OS) const254f2001aa7SIlya Biryukov   llvm::raw_ostream &dump(llvm::raw_ostream &OS) const override {
255f2001aa7SIlya Biryukov     return OS << "true";
256f2001aa7SIlya Biryukov   }
25730ffdf42SKirill Bobyrev 
25830ffdf42SKirill Bobyrev   DocID Index = 0;
25930ffdf42SKirill Bobyrev   /// Size of the underlying virtual PostingList.
26030ffdf42SKirill Bobyrev   DocID Size;
26130ffdf42SKirill Bobyrev };
26230ffdf42SKirill Bobyrev 
26387f69eafSSam McCall /// FalseIterator yields no results.
26487f69eafSSam McCall class FalseIterator : public Iterator {
26587f69eafSSam McCall public:
FalseIterator()26687f69eafSSam McCall   FalseIterator() : Iterator(Kind::False) {}
reachedEnd() const26787f69eafSSam McCall   bool reachedEnd() const override { return true; }
advance()26887f69eafSSam McCall   void advance() override { assert(false); }
advanceTo(DocID ID)26987f69eafSSam McCall   void advanceTo(DocID ID) override { assert(false); }
peek() const27087f69eafSSam McCall   DocID peek() const override {
27187f69eafSSam McCall     assert(false);
27287f69eafSSam McCall     return 0;
27387f69eafSSam McCall   }
consume()27487f69eafSSam McCall   float consume() override {
27587f69eafSSam McCall     assert(false);
27687f69eafSSam McCall     return 1;
27787f69eafSSam McCall   }
estimateSize() const27887f69eafSSam McCall   size_t estimateSize() const override { return 0; }
27987f69eafSSam McCall 
28087f69eafSSam McCall private:
dump(llvm::raw_ostream & OS) const281f2001aa7SIlya Biryukov   llvm::raw_ostream &dump(llvm::raw_ostream &OS) const override {
282f2001aa7SIlya Biryukov     return OS << "false";
283f2001aa7SIlya Biryukov   }
28487f69eafSSam McCall };
28587f69eafSSam McCall 
2867413e985SKirill Bobyrev /// Boost iterator is a wrapper around its child which multiplies scores of
2877413e985SKirill Bobyrev /// each retrieved item by a given factor.
2887413e985SKirill Bobyrev class BoostIterator : public Iterator {
2897413e985SKirill Bobyrev public:
BoostIterator(std::unique_ptr<Iterator> Child,float Factor)2907413e985SKirill Bobyrev   BoostIterator(std::unique_ptr<Iterator> Child, float Factor)
29187f69eafSSam McCall       : Child(std::move(Child)), Factor(Factor) {}
2927413e985SKirill Bobyrev 
reachedEnd() const2937413e985SKirill Bobyrev   bool reachedEnd() const override { return Child->reachedEnd(); }
2947413e985SKirill Bobyrev 
advance()2957413e985SKirill Bobyrev   void advance() override { Child->advance(); }
2967413e985SKirill Bobyrev 
advanceTo(DocID ID)2977413e985SKirill Bobyrev   void advanceTo(DocID ID) override { Child->advanceTo(ID); }
2987413e985SKirill Bobyrev 
peek() const2997413e985SKirill Bobyrev   DocID peek() const override { return Child->peek(); }
3007413e985SKirill Bobyrev 
consume()301a98961bcSKirill Bobyrev   float consume() override { return Child->consume() * Factor; }
3027413e985SKirill Bobyrev 
estimateSize() const30338bdac5dSKirill Bobyrev   size_t estimateSize() const override { return Child->estimateSize(); }
30438bdac5dSKirill Bobyrev 
3057413e985SKirill Bobyrev private:
dump(llvm::raw_ostream & OS) const306f2001aa7SIlya Biryukov   llvm::raw_ostream &dump(llvm::raw_ostream &OS) const override {
30774028360SSam McCall     return OS << "(* " << Factor << ' ' << *Child << ')';
3087413e985SKirill Bobyrev   }
3097413e985SKirill Bobyrev 
3107413e985SKirill Bobyrev   std::unique_ptr<Iterator> Child;
3117413e985SKirill Bobyrev   float Factor;
3127413e985SKirill Bobyrev };
3137413e985SKirill Bobyrev 
314a98961bcSKirill Bobyrev /// This iterator limits the number of items retrieved from the child iterator
315a98961bcSKirill Bobyrev /// on top of the query tree. To ensure that query tree with LIMIT iterators
316a98961bcSKirill Bobyrev /// inside works correctly, users have to call Root->consume(Root->peek()) each
317a98961bcSKirill Bobyrev /// time item is retrieved at the root of query tree.
318a98961bcSKirill Bobyrev class LimitIterator : public Iterator {
319a98961bcSKirill Bobyrev public:
LimitIterator(std::unique_ptr<Iterator> Child,size_t Limit)320a98961bcSKirill Bobyrev   LimitIterator(std::unique_ptr<Iterator> Child, size_t Limit)
32187f69eafSSam McCall       : Child(std::move(Child)), Limit(Limit), ItemsLeft(Limit) {}
322a98961bcSKirill Bobyrev 
reachedEnd() const323a98961bcSKirill Bobyrev   bool reachedEnd() const override {
324a98961bcSKirill Bobyrev     return ItemsLeft == 0 || Child->reachedEnd();
325a98961bcSKirill Bobyrev   }
326a98961bcSKirill Bobyrev 
advance()327a98961bcSKirill Bobyrev   void advance() override { Child->advance(); }
328a98961bcSKirill Bobyrev 
advanceTo(DocID ID)329a98961bcSKirill Bobyrev   void advanceTo(DocID ID) override { Child->advanceTo(ID); }
330a98961bcSKirill Bobyrev 
peek() const331a98961bcSKirill Bobyrev   DocID peek() const override { return Child->peek(); }
332a98961bcSKirill Bobyrev 
333a98961bcSKirill Bobyrev   /// Decreases the limit in case the element consumed at top of the query tree
334a98961bcSKirill Bobyrev   /// comes from the underlying iterator.
consume()335a98961bcSKirill Bobyrev   float consume() override {
336493b1627SKirill Bobyrev     assert(!reachedEnd() && "LimitIterator can't consume() at the end.");
337a98961bcSKirill Bobyrev     --ItemsLeft;
338a98961bcSKirill Bobyrev     return Child->consume();
339a98961bcSKirill Bobyrev   }
340a98961bcSKirill Bobyrev 
estimateSize() const34138bdac5dSKirill Bobyrev   size_t estimateSize() const override {
34238bdac5dSKirill Bobyrev     return std::min(Child->estimateSize(), Limit);
34338bdac5dSKirill Bobyrev   }
34438bdac5dSKirill Bobyrev 
345a98961bcSKirill Bobyrev private:
dump(llvm::raw_ostream & OS) const346f2001aa7SIlya Biryukov   llvm::raw_ostream &dump(llvm::raw_ostream &OS) const override {
34774028360SSam McCall     return OS << "(LIMIT " << Limit << " " << *Child << ')';
348a98961bcSKirill Bobyrev   }
349a98961bcSKirill Bobyrev 
350a98961bcSKirill Bobyrev   std::unique_ptr<Iterator> Child;
351a98961bcSKirill Bobyrev   size_t Limit;
352a98961bcSKirill Bobyrev   size_t ItemsLeft;
353a98961bcSKirill Bobyrev };
354a98961bcSKirill Bobyrev 
355a522c1cfSKirill Bobyrev } // end namespace
356a522c1cfSKirill Bobyrev 
consume(Iterator & It)357a98961bcSKirill Bobyrev std::vector<std::pair<DocID, float>> consume(Iterator &It) {
3587413e985SKirill Bobyrev   std::vector<std::pair<DocID, float>> Result;
359a98961bcSKirill Bobyrev   for (; !It.reachedEnd(); It.advance())
360493b1627SKirill Bobyrev     Result.emplace_back(It.peek(), It.consume());
361a522c1cfSKirill Bobyrev   return Result;
362a522c1cfSKirill Bobyrev }
363a522c1cfSKirill Bobyrev 
364a522c1cfSKirill Bobyrev std::unique_ptr<Iterator>
intersect(std::vector<std::unique_ptr<Iterator>> Children) const365a659d779SSam McCall Corpus::intersect(std::vector<std::unique_ptr<Iterator>> Children) const {
36687f69eafSSam McCall   std::vector<std::unique_ptr<Iterator>> RealChildren;
36787f69eafSSam McCall   for (auto &Child : Children) {
36887f69eafSSam McCall     switch (Child->kind()) {
36987f69eafSSam McCall     case Iterator::Kind::True:
37087f69eafSSam McCall       break; // No effect, drop the iterator.
37187f69eafSSam McCall     case Iterator::Kind::False:
37287f69eafSSam McCall       return std::move(Child); // Intersection is empty.
37387f69eafSSam McCall     case Iterator::Kind::And: {
37487f69eafSSam McCall       // Inline nested AND into parent AND.
37587f69eafSSam McCall       auto &NewChildren = static_cast<AndIterator *>(Child.get())->Children;
37687f69eafSSam McCall       std::move(NewChildren.begin(), NewChildren.end(),
37787f69eafSSam McCall                 std::back_inserter(RealChildren));
37887f69eafSSam McCall       break;
37987f69eafSSam McCall     }
38087f69eafSSam McCall     default:
38187f69eafSSam McCall       RealChildren.push_back(std::move(Child));
38287f69eafSSam McCall     }
38387f69eafSSam McCall   }
38487f69eafSSam McCall   switch (RealChildren.size()) {
38587f69eafSSam McCall   case 0:
38687f69eafSSam McCall     return all();
38787f69eafSSam McCall   case 1:
38887f69eafSSam McCall     return std::move(RealChildren.front());
38987f69eafSSam McCall   default:
3901c705d9cSJonas Devlieghere     return std::make_unique<AndIterator>(std::move(RealChildren));
39187f69eafSSam McCall   }
392a522c1cfSKirill Bobyrev }
393a522c1cfSKirill Bobyrev 
394a522c1cfSKirill Bobyrev std::unique_ptr<Iterator>
unionOf(std::vector<std::unique_ptr<Iterator>> Children) const395a659d779SSam McCall Corpus::unionOf(std::vector<std::unique_ptr<Iterator>> Children) const {
39687f69eafSSam McCall   std::vector<std::unique_ptr<Iterator>> RealChildren;
39787f69eafSSam McCall   for (auto &Child : Children) {
39887f69eafSSam McCall     switch (Child->kind()) {
39987f69eafSSam McCall     case Iterator::Kind::False:
40087f69eafSSam McCall       break; // No effect, drop the iterator.
40187f69eafSSam McCall     case Iterator::Kind::Or: {
40287f69eafSSam McCall       // Inline nested OR into parent OR.
40387f69eafSSam McCall       auto &NewChildren = static_cast<OrIterator *>(Child.get())->Children;
40487f69eafSSam McCall       std::move(NewChildren.begin(), NewChildren.end(),
40587f69eafSSam McCall                 std::back_inserter(RealChildren));
40687f69eafSSam McCall       break;
40787f69eafSSam McCall     }
40887f69eafSSam McCall     case Iterator::Kind::True:
40987f69eafSSam McCall       // Don't return all(), which would discard sibling boosts.
41087f69eafSSam McCall     default:
41187f69eafSSam McCall       RealChildren.push_back(std::move(Child));
41287f69eafSSam McCall     }
41387f69eafSSam McCall   }
41487f69eafSSam McCall   switch (RealChildren.size()) {
41587f69eafSSam McCall   case 0:
41687f69eafSSam McCall     return none();
41787f69eafSSam McCall   case 1:
41887f69eafSSam McCall     return std::move(RealChildren.front());
41987f69eafSSam McCall   default:
4201c705d9cSJonas Devlieghere     return std::make_unique<OrIterator>(std::move(RealChildren));
42187f69eafSSam McCall   }
422a522c1cfSKirill Bobyrev }
423a522c1cfSKirill Bobyrev 
all() const424a659d779SSam McCall std::unique_ptr<Iterator> Corpus::all() const {
4251c705d9cSJonas Devlieghere   return std::make_unique<TrueIterator>(Size);
42630ffdf42SKirill Bobyrev }
42730ffdf42SKirill Bobyrev 
none() const42887f69eafSSam McCall std::unique_ptr<Iterator> Corpus::none() const {
4291c705d9cSJonas Devlieghere   return std::make_unique<FalseIterator>();
43087f69eafSSam McCall }
43187f69eafSSam McCall 
boost(std::unique_ptr<Iterator> Child,float Factor) const432a659d779SSam McCall std::unique_ptr<Iterator> Corpus::boost(std::unique_ptr<Iterator> Child,
433a659d779SSam McCall                                         float Factor) const {
43487f69eafSSam McCall   if (Factor == 1)
43587f69eafSSam McCall     return Child;
43687f69eafSSam McCall   if (Child->kind() == Iterator::Kind::False)
43787f69eafSSam McCall     return Child;
4381c705d9cSJonas Devlieghere   return std::make_unique<BoostIterator>(std::move(Child), Factor);
4397413e985SKirill Bobyrev }
4407413e985SKirill Bobyrev 
limit(std::unique_ptr<Iterator> Child,size_t Limit) const441a659d779SSam McCall std::unique_ptr<Iterator> Corpus::limit(std::unique_ptr<Iterator> Child,
442a659d779SSam McCall                                         size_t Limit) const {
44387f69eafSSam McCall   if (Child->kind() == Iterator::Kind::False)
44487f69eafSSam McCall     return Child;
4451c705d9cSJonas Devlieghere   return std::make_unique<LimitIterator>(std::move(Child), Limit);
446a98961bcSKirill Bobyrev }
447a98961bcSKirill Bobyrev 
448a522c1cfSKirill Bobyrev } // namespace dex
449a522c1cfSKirill Bobyrev } // namespace clangd
450a522c1cfSKirill Bobyrev } // namespace clang
451