Coverage Report

Created: 2026-07-16 06:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/proc/self/cwd/eval/eval/lazy_init_step.cc
Line
Count
Source
1
// Copyright 2023 Google LLC
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#include "eval/eval/lazy_init_step.h"
16
17
#include <cstddef>
18
#include <cstdint>
19
#include <memory>
20
#include <utility>
21
22
#include "cel/expr/value.pb.h"
23
#include "absl/base/nullability.h"
24
#include "absl/status/status.h"
25
#include "common/value.h"
26
#include "eval/eval/attribute_trail.h"
27
#include "eval/eval/comprehension_slots.h"
28
#include "eval/eval/direct_expression_step.h"
29
#include "eval/eval/evaluator_core.h"
30
#include "eval/eval/expression_step_base.h"
31
#include "internal/status_macros.h"
32
33
namespace google::api::expr::runtime {
34
35
namespace {
36
37
using ::cel::Value;
38
39
class LazyInitStep final : public ExpressionStepBase {
40
 public:
41
  LazyInitStep(size_t slot_index, size_t subexpression_index, int64_t expr_id)
42
0
      : ExpressionStepBase(expr_id),
43
0
        slot_index_(slot_index),
44
0
        subexpression_index_(subexpression_index) {}
45
46
0
  absl::Status Evaluate(ExecutionFrame* frame) const override {
47
0
    ComprehensionSlot* slot = frame->comprehension_slots().Get(slot_index_);
48
0
    if (slot->Has()) {
49
0
      frame->value_stack().Push(slot->value(), slot->attribute());
50
0
    } else {
51
0
      frame->Call(slot_index_, subexpression_index_);
52
0
    }
53
0
    return absl::OkStatus();
54
0
  }
55
56
 private:
57
  const size_t slot_index_;
58
  const size_t subexpression_index_;
59
};
60
61
class DirectLazyInitStep final : public DirectExpressionStep {
62
 public:
63
  DirectLazyInitStep(size_t slot_index,
64
                     const DirectExpressionStep* subexpression, int64_t expr_id)
65
0
      : DirectExpressionStep(expr_id),
66
0
        slot_index_(slot_index),
67
0
        subexpression_(subexpression) {}
68
69
  absl::Status Evaluate(ExecutionFrameBase& frame, Value& result,
70
0
                        AttributeTrail& attribute) const override {
71
0
    ComprehensionSlot* slot = frame.comprehension_slots().Get(slot_index_);
72
0
    if (slot->Has()) {
73
0
      result = slot->value();
74
0
      attribute = slot->attribute();
75
0
    } else {
76
0
      CEL_RETURN_IF_ERROR(subexpression_->Evaluate(frame, result, attribute));
77
0
      slot->Set(result, attribute);
78
0
    }
79
0
    return absl::OkStatus();
80
0
  }
81
82
 private:
83
  const size_t slot_index_;
84
  const DirectExpressionStep* absl_nonnull const subexpression_;
85
};
86
87
class BindStep : public DirectExpressionStep {
88
 public:
89
  BindStep(size_t slot_index,
90
           std::unique_ptr<DirectExpressionStep> subexpression, int64_t expr_id)
91
0
      : DirectExpressionStep(expr_id),
92
0
        slot_index_(slot_index),
93
0
        subexpression_(std::move(subexpression)) {}
94
95
  absl::Status Evaluate(ExecutionFrameBase& frame, Value& result,
96
0
                        AttributeTrail& attribute) const override {
97
0
    CEL_RETURN_IF_ERROR(subexpression_->Evaluate(frame, result, attribute));
98
99
0
    frame.comprehension_slots().ClearSlot(slot_index_);
100
101
0
    return absl::OkStatus();
102
0
  }
103
104
 private:
105
  size_t slot_index_;
106
  std::unique_ptr<DirectExpressionStep> subexpression_;
107
};
108
109
class AssignSlotAndPopStepStep final : public ExpressionStepBase {
110
 public:
111
  explicit AssignSlotAndPopStepStep(size_t slot_index)
112
0
      : ExpressionStepBase(/*expr_id=*/-1, /*comes_from_ast=*/false),
113
0
        slot_index_(slot_index) {}
114
115
0
  absl::Status Evaluate(ExecutionFrame* frame) const override {
116
0
    if (!frame->value_stack().HasEnough(1)) {
117
0
      return absl::InternalError("Stack underflow assigning lazy value");
118
0
    }
119
120
0
    frame->comprehension_slots().Set(slot_index_, frame->value_stack().Peek(),
121
0
                                     frame->value_stack().PeekAttribute());
122
0
    frame->value_stack().Pop(1);
123
124
0
    return absl::OkStatus();
125
0
  }
126
127
 private:
128
  const size_t slot_index_;
129
};
130
131
class ClearSlotStep : public ExpressionStepBase {
132
 public:
133
  explicit ClearSlotStep(size_t slot_index, int64_t expr_id)
134
0
      : ExpressionStepBase(expr_id), slot_index_(slot_index) {}
135
136
0
  absl::Status Evaluate(ExecutionFrame* frame) const override {
137
0
    frame->comprehension_slots().ClearSlot(slot_index_);
138
0
    return absl::OkStatus();
139
0
  }
140
141
 private:
142
  size_t slot_index_;
143
};
144
145
class ClearSlotsStep final : public ExpressionStepBase {
146
 public:
147
  explicit ClearSlotsStep(size_t slot_index, size_t slot_count, int64_t expr_id)
148
0
      : ExpressionStepBase(expr_id),
149
0
        slot_index_(slot_index),
150
0
        slot_count_(slot_count) {}
151
152
0
  absl::Status Evaluate(ExecutionFrame* frame) const override {
153
0
    for (size_t i = 0; i < slot_count_; ++i) {
154
0
      frame->comprehension_slots().ClearSlot(slot_index_ + i);
155
0
    }
156
0
    return absl::OkStatus();
157
0
  }
158
159
 private:
160
  const size_t slot_index_;
161
  const size_t slot_count_;
162
};
163
164
class BlockStep : public DirectExpressionStep {
165
 public:
166
  BlockStep(size_t slot_index, size_t slot_count,
167
            std::unique_ptr<DirectExpressionStep> subexpression,
168
            int64_t expr_id)
169
0
      : DirectExpressionStep(expr_id),
170
0
        slot_index_(slot_index),
171
0
        slot_count_(slot_count),
172
0
        subexpression_(std::move(subexpression)) {}
173
174
  absl::Status Evaluate(ExecutionFrameBase& frame, Value& result,
175
0
                        AttributeTrail& attribute) const override {
176
0
    CEL_RETURN_IF_ERROR(subexpression_->Evaluate(frame, result, attribute));
177
178
0
    for (size_t i = 0; i < slot_count_; ++i) {
179
0
      frame.comprehension_slots().ClearSlot(slot_index_ + i);
180
0
    }
181
182
0
    return absl::OkStatus();
183
0
  }
184
185
 private:
186
  size_t slot_index_;
187
  size_t slot_count_;
188
  std::unique_ptr<DirectExpressionStep> subexpression_;
189
};
190
191
}  // namespace
192
193
std::unique_ptr<DirectExpressionStep> CreateDirectBindStep(
194
    size_t slot_index, std::unique_ptr<DirectExpressionStep> expression,
195
0
    int64_t expr_id) {
196
0
  return std::make_unique<BindStep>(slot_index, std::move(expression), expr_id);
197
0
}
198
199
std::unique_ptr<DirectExpressionStep> CreateDirectBlockStep(
200
    size_t slot_index, size_t slot_count,
201
0
    std::unique_ptr<DirectExpressionStep> expression, int64_t expr_id) {
202
0
  return std::make_unique<BlockStep>(slot_index, slot_count,
203
0
                                     std::move(expression), expr_id);
204
0
}
205
206
std::unique_ptr<DirectExpressionStep> CreateDirectLazyInitStep(
207
    size_t slot_index, const DirectExpressionStep* absl_nonnull subexpression,
208
0
    int64_t expr_id) {
209
0
  return std::make_unique<DirectLazyInitStep>(slot_index, subexpression,
210
0
                                              expr_id);
211
0
}
212
213
std::unique_ptr<ExpressionStep> CreateLazyInitStep(size_t slot_index,
214
                                                   size_t subexpression_index,
215
0
                                                   int64_t expr_id) {
216
0
  return std::make_unique<LazyInitStep>(slot_index, subexpression_index,
217
0
                                        expr_id);
218
0
}
219
220
0
std::unique_ptr<ExpressionStep> CreateAssignSlotAndPopStep(size_t slot_index) {
221
0
  return std::make_unique<AssignSlotAndPopStepStep>(slot_index);
222
0
}
223
224
std::unique_ptr<ExpressionStep> CreateClearSlotStep(size_t slot_index,
225
0
                                                    int64_t expr_id) {
226
0
  return std::make_unique<ClearSlotStep>(slot_index, expr_id);
227
0
}
228
229
std::unique_ptr<ExpressionStep> CreateClearSlotsStep(size_t slot_index,
230
                                                     size_t slot_count,
231
                                                     int64_t expr_id) {
232
  ABSL_DCHECK_GT(slot_count, 0);
233
  return std::make_unique<ClearSlotsStep>(slot_index, slot_count, expr_id);
234
}
235
236
}  // namespace google::api::expr::runtime