Skip to content

Commit 798d60c

Browse files
committed
[Evaluator] Add a Caching template parameter to SimpleRequest.
Simplify the definition of new request kinds by pulling the parameterization of caching logic into SimpleRequest itself, so that the caching-related parts of the contract cannot easily be forgotten.
1 parent 44099ad commit 798d60c

File tree

2 files changed

+45
-25
lines changed

2 files changed

+45
-25
lines changed

include/swift/AST/SimpleRequest.h

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,45 +29,68 @@ namespace swift {
2929

3030
class Evaluator;
3131

32+
/// Describes how the result for a particular request will be cached.
33+
enum class CacheKind {
34+
/// The result for a particular request should never be cached.
35+
Uncached,
36+
/// The result for a particular request should be cached within the
37+
/// evaluator itself.
38+
Cached,
39+
/// The result of a particular request will be cached via some separate
40+
/// mechanism, such as a mutable data structure.
41+
SeparatelyCached,
42+
};
43+
3244
/// CRTP base class that describes a request operation that takes values
3345
/// with the given input types (\c Inputs...) and produces an output of
3446
/// the given type.
3547
///
3648
/// \tparam Derived The final, derived class type for the request.
49+
/// \tparam Caching Describes how the output value is cached, if at all.
3750
/// \tparam Output The type of the result produced by evaluating this request.
3851
/// \tparam Inputs The types of the inputs to this request, i.e., the values
3952
/// that comprise the request itself. These will determine the uniqueness of
4053
/// the request.
4154
///
42-
/// The Derived class needs to implement several operations. The most important
43-
/// one takes an evaluator and the input values, then computes the final
44-
/// result:
55+
/// The \c Derived class needs to implement several operations. The most
56+
/// important one takes an evaluator and the input values, then computes the
57+
/// final result:
4558
/// \code
4659
/// Output operator()(Evaluator &evaluator, Inputs...) const;
4760
/// \endcode
4861
///
49-
/// The Derived class will also need to implement an operation to break a
62+
/// The \c Derived class will also need to implement an operation to break a
5063
/// cycle if one is found, i.e.,
5164
/// \code
5265
/// OutputType breakCycle() const;
5366
/// \endcode
5467
///
55-
/// Cycle diagnostics can be handled in one of two ways. Either the Derived
68+
/// Cycle diagnostics can be handled in one of two ways. Either the \c Derived
5669
/// class can implement the two cycle-diagnosing operations directly:
5770
/// \code
5871
/// void diagnoseCycle(DiagnosticEngine &diags) const;
5972
/// void noteCycleStep(DiagnosticEngine &diags) const;
6073
/// \endcode
6174
///
62-
/// Or the Derived class can provide a "diagnostic location" operation and
75+
/// Or the \c Derived class can provide a "diagnostic location" operation and
6376
/// diagnostic values for the main cycle diagnostic and a "note" describing a
6477
/// step within the chain of diagnostics:
6578
/// \code
6679
/// T getCycleDiagnosticLoc(Inputs...) const;
6780
/// static constexpr Diag<Inputs...> cycleDiagnostic = ...;
6881
/// static constexpr Diag<Inputs...> cycleStepDiagnostic = ...;
6982
/// \endcode
70-
template<typename Derived, typename Output, typename ...Inputs>
83+
///
84+
/// Value caching is determined by the \c Caching parameter. When
85+
/// \c Caching == CacheKind::SeparatelyCached, the \c Derived class is
86+
/// responsible for implementing the two operations responsible to managing
87+
/// the cache:
88+
/// \code
89+
/// Optional<Output> getCachedResult() const;
90+
/// void cacheResult(Output value) const;
91+
/// \endcode
92+
template<typename Derived, CacheKind Caching, typename Output,
93+
typename ...Inputs>
7194
class SimpleRequest {
7295
std::tuple<Inputs...> storage;
7396

@@ -99,6 +122,9 @@ class SimpleRequest {
99122
const std::tuple<Inputs...> &getStorage() const { return storage; }
100123

101124
public:
125+
static const bool isEverCached = (Caching != CacheKind::Uncached);
126+
static const bool hasExternalCache = (Caching == CacheKind::SeparatelyCached);
127+
102128
using OutputType = Output;
103129

104130
explicit SimpleRequest(const Inputs& ...inputs)

unittests/AST/ArithmeticEvaluator.cpp

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,12 @@ void simple_display(llvm::raw_ostream &out, ArithmeticExpr *expr) {
8282
}
8383

8484
/// Rule to evaluate the value of the expression.
85-
template<typename Derived>
85+
template<typename Derived, CacheKind Caching>
8686
struct EvaluationRule
87-
: public SimpleRequest<Derived, double, ArithmeticExpr *>
87+
: public SimpleRequest<Derived, Caching, double, ArithmeticExpr *>
8888
{
89-
using SimpleRequest<Derived, double, ArithmeticExpr *>::SimpleRequest;
90-
using SimpleRequest<Derived, double, ArithmeticExpr *>::operator();
89+
using SimpleRequest<Derived, Caching, double, ArithmeticExpr *>::SimpleRequest;
90+
using SimpleRequest<Derived, Caching, double, ArithmeticExpr *>::operator();
9191

9292
double operator()(Evaluator &evaluator, ArithmeticExpr *expr) const {
9393
switch (expr->kind) {
@@ -122,15 +122,12 @@ struct EvaluationRule
122122
void noteCycleStep(DiagnosticEngine &diags) const { }
123123
};
124124

125-
template<typename Derived>
126-
bool EvaluationRule<Derived>::brokeCycle = false;
125+
template<typename Derived, CacheKind Caching>
126+
bool EvaluationRule<Derived, Caching>::brokeCycle = false;
127127

128128
struct InternallyCachedEvaluationRule :
129-
EvaluationRule<InternallyCachedEvaluationRule>
129+
EvaluationRule<InternallyCachedEvaluationRule, CacheKind::Cached>
130130
{
131-
static const bool isEverCached = true;
132-
static const bool hasExternalCache = false;
133-
134131
using EvaluationRule::EvaluationRule;
135132

136133
bool isCached() const {
@@ -145,17 +142,14 @@ struct InternallyCachedEvaluationRule :
145142
}
146143
};
147144

148-
struct UncachedEvaluationRule : EvaluationRule<UncachedEvaluationRule> {
149-
static const bool isEverCached = false;
150-
145+
struct UncachedEvaluationRule
146+
: EvaluationRule<UncachedEvaluationRule, CacheKind::Uncached> {
151147
using EvaluationRule::EvaluationRule;
152148
};
153149

154-
struct ExternallyCachedEvaluationRule :
155-
EvaluationRule<ExternallyCachedEvaluationRule> {
156-
static const bool isEverCached = true;
157-
static const bool hasExternalCache = true;
158-
150+
struct ExternallyCachedEvaluationRule
151+
: EvaluationRule<ExternallyCachedEvaluationRule,
152+
CacheKind::SeparatelyCached> {
159153
using EvaluationRule::EvaluationRule;
160154

161155
bool isCached() const {

0 commit comments

Comments
 (0)