/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 |