Skip to content

Commit 0cfbe8c

Browse files
committed
[NFC] Introduce a little generators library
1 parent a05fef5 commit 0cfbe8c

File tree

2 files changed

+139
-0
lines changed

2 files changed

+139
-0
lines changed

include/swift/Basic/ArrayRefView.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,17 @@ template<typename Orig, typename Projected>
167167
using CastArrayRefView =
168168
ArrayRefView<Orig, Projected *, arrayRefViewCastHelper<Projected, Orig>>;
169169

170+
namespace generator_details {
171+
template <class T> struct is_array_ref_like;
172+
173+
template <class Orig, class Projected, Projected (&Project)(const Orig &),
174+
bool AllowOrigAccess>
175+
struct is_array_ref_like<ArrayRefView<Orig, Projected, Project,
176+
AllowOrigAccess>> {
177+
enum { value = true };
178+
};
179+
}
180+
170181
} // end namespace swift
171182

172183
#endif // SWIFT_BASIC_ARRAYREFVIEW_H

include/swift/Basic/Generators.h

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
//===--- Generators.h - "Coroutines" for doing traversals -------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file defines a basic generator concept and some useful common
14+
// implementations of it.
15+
//
16+
// concept Generator {
17+
// // ...some number of accessors for the current value...
18+
//
19+
// /// Is this generator finished producing values?
20+
// bool isFinished() const;
21+
//
22+
// /// Given that this generator is not finished, advance to the
23+
// /// next value.
24+
// void advance();
25+
//
26+
// /// Finish the generator, asserting that all values have been
27+
// /// produced.
28+
// void finish();
29+
// };
30+
//
31+
//===----------------------------------------------------------------------===//
32+
33+
#ifndef SWIFT_BASIC_GENERATORS_H
34+
#define SWIFT_BASIC_GENERATORS_H
35+
36+
#include "llvm/ADT/ArrayRef.h"
37+
38+
namespace swift {
39+
40+
namespace generator_details {
41+
42+
template <class T>
43+
struct is_array_ref_like {
44+
enum { value = false };
45+
};
46+
47+
template <class T>
48+
struct is_array_ref_like<llvm::ArrayRef<T>> {
49+
enum { value = true };
50+
};
51+
52+
template <class T>
53+
struct is_array_ref_like<llvm::MutableArrayRef<T>> {
54+
enum { value = true };
55+
};
56+
}
57+
58+
/// A class for generating the elements of an ArrayRef-like collection.
59+
template <class CollectionType>
60+
class ArrayRefGenerator {
61+
static_assert(generator_details::is_array_ref_like<CollectionType>::value,
62+
"ArrayRefGenerator should only be used with ArrayRef-like "
63+
"types");
64+
65+
CollectionType values;
66+
67+
public:
68+
using reference =
69+
typename std::iterator_traits<typename CollectionType::iterator>::reference;
70+
71+
ArrayRefGenerator() {}
72+
ArrayRefGenerator(CollectionType values) : values(values) {}
73+
74+
// Prevent accidental copying of the generator.
75+
ArrayRefGenerator(const ArrayRefGenerator &other) = delete;
76+
ArrayRefGenerator &operator=(const ArrayRefGenerator &other) = delete;
77+
78+
ArrayRefGenerator(ArrayRefGenerator &&other) = default;
79+
ArrayRefGenerator &operator=(ArrayRefGenerator &&other) = default;
80+
81+
/// Explicitly copy the current generator state.
82+
ArrayRefGenerator clone() const {
83+
return ArrayRefGenerator(values);
84+
}
85+
86+
/// Return the current element of the array.
87+
reference getCurrent() const {
88+
assert(!isFinished());
89+
return values.front();
90+
}
91+
92+
/// Claim the current element of the array and advance past it.
93+
reference claimNext() {
94+
assert(!isFinished());
95+
reference result = getCurrent();
96+
advance();
97+
return result;
98+
}
99+
100+
/// Claim the next N elements of the array and advance past them.
101+
CollectionType claimNext(size_t count) {
102+
assert(count <= values.size() && "claiming too many values");
103+
CollectionType result = values.slice(0, count);
104+
values = values.slice(count);
105+
return result;
106+
}
107+
108+
/// Is this generation finished?
109+
bool isFinished() const {
110+
return values.empty();
111+
}
112+
113+
/// Given that this generation is not finished, advance to the
114+
/// next element.
115+
void advance() {
116+
assert(!isFinished());
117+
values = values.slice(1);
118+
}
119+
120+
/// Perform any final work required to complete the generation.
121+
void finish() {
122+
assert(isFinished() && "didn't finish generating the collection");
123+
}
124+
};
125+
126+
} // end namespace swift
127+
128+
#endif

0 commit comments

Comments
 (0)