mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[NFC] Introduce a little generators library
This commit is contained in:
@@ -167,6 +167,17 @@ template<typename Orig, typename Projected>
|
|||||||
using CastArrayRefView =
|
using CastArrayRefView =
|
||||||
ArrayRefView<Orig, Projected *, arrayRefViewCastHelper<Projected, Orig>>;
|
ArrayRefView<Orig, Projected *, arrayRefViewCastHelper<Projected, Orig>>;
|
||||||
|
|
||||||
|
namespace generator_details {
|
||||||
|
template <class T> struct is_array_ref_like;
|
||||||
|
|
||||||
|
template <class Orig, class Projected, Projected (&Project)(const Orig &),
|
||||||
|
bool AllowOrigAccess>
|
||||||
|
struct is_array_ref_like<ArrayRefView<Orig, Projected, Project,
|
||||||
|
AllowOrigAccess>> {
|
||||||
|
enum { value = true };
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
} // end namespace swift
|
} // end namespace swift
|
||||||
|
|
||||||
#endif // SWIFT_BASIC_ARRAYREFVIEW_H
|
#endif // SWIFT_BASIC_ARRAYREFVIEW_H
|
||||||
|
|||||||
128
include/swift/Basic/Generators.h
Normal file
128
include/swift/Basic/Generators.h
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
//===--- Generators.h - "Coroutines" for doing traversals -------*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// This source file is part of the Swift.org open source project
|
||||||
|
//
|
||||||
|
// Copyright (c) 2023 Apple Inc. and the Swift project authors
|
||||||
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||||
|
//
|
||||||
|
// See https://swift.org/LICENSE.txt for license information
|
||||||
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file defines a basic generator concept and some useful common
|
||||||
|
// implementations of it.
|
||||||
|
//
|
||||||
|
// concept Generator {
|
||||||
|
// // ...some number of accessors for the current value...
|
||||||
|
//
|
||||||
|
// /// Is this generator finished producing values?
|
||||||
|
// bool isFinished() const;
|
||||||
|
//
|
||||||
|
// /// Given that this generator is not finished, advance to the
|
||||||
|
// /// next value.
|
||||||
|
// void advance();
|
||||||
|
//
|
||||||
|
// /// Finish the generator, asserting that all values have been
|
||||||
|
// /// produced.
|
||||||
|
// void finish();
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef SWIFT_BASIC_GENERATORS_H
|
||||||
|
#define SWIFT_BASIC_GENERATORS_H
|
||||||
|
|
||||||
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
|
|
||||||
|
namespace swift {
|
||||||
|
|
||||||
|
namespace generator_details {
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct is_array_ref_like {
|
||||||
|
enum { value = false };
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct is_array_ref_like<llvm::ArrayRef<T>> {
|
||||||
|
enum { value = true };
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct is_array_ref_like<llvm::MutableArrayRef<T>> {
|
||||||
|
enum { value = true };
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A class for generating the elements of an ArrayRef-like collection.
|
||||||
|
template <class CollectionType>
|
||||||
|
class ArrayRefGenerator {
|
||||||
|
static_assert(generator_details::is_array_ref_like<CollectionType>::value,
|
||||||
|
"ArrayRefGenerator should only be used with ArrayRef-like "
|
||||||
|
"types");
|
||||||
|
|
||||||
|
CollectionType values;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using reference =
|
||||||
|
typename std::iterator_traits<typename CollectionType::iterator>::reference;
|
||||||
|
|
||||||
|
ArrayRefGenerator() {}
|
||||||
|
ArrayRefGenerator(CollectionType values) : values(values) {}
|
||||||
|
|
||||||
|
// Prevent accidental copying of the generator.
|
||||||
|
ArrayRefGenerator(const ArrayRefGenerator &other) = delete;
|
||||||
|
ArrayRefGenerator &operator=(const ArrayRefGenerator &other) = delete;
|
||||||
|
|
||||||
|
ArrayRefGenerator(ArrayRefGenerator &&other) = default;
|
||||||
|
ArrayRefGenerator &operator=(ArrayRefGenerator &&other) = default;
|
||||||
|
|
||||||
|
/// Explicitly copy the current generator state.
|
||||||
|
ArrayRefGenerator clone() const {
|
||||||
|
return ArrayRefGenerator(values);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the current element of the array.
|
||||||
|
reference getCurrent() const {
|
||||||
|
assert(!isFinished());
|
||||||
|
return values.front();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Claim the current element of the array and advance past it.
|
||||||
|
reference claimNext() {
|
||||||
|
assert(!isFinished());
|
||||||
|
reference result = getCurrent();
|
||||||
|
advance();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Claim the next N elements of the array and advance past them.
|
||||||
|
CollectionType claimNext(size_t count) {
|
||||||
|
assert(count <= values.size() && "claiming too many values");
|
||||||
|
CollectionType result = values.slice(0, count);
|
||||||
|
values = values.slice(count);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Is this generation finished?
|
||||||
|
bool isFinished() const {
|
||||||
|
return values.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Given that this generation is not finished, advance to the
|
||||||
|
/// next element.
|
||||||
|
void advance() {
|
||||||
|
assert(!isFinished());
|
||||||
|
values = values.slice(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Perform any final work required to complete the generation.
|
||||||
|
void finish() {
|
||||||
|
assert(isFinished() && "didn't finish generating the collection");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end namespace swift
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user