/proc/self/cwd/common/ast/expr_proto.cc
Line | Count | Source |
1 | | // Copyright 2024 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 "common/ast/expr_proto.h" |
16 | | |
17 | | #include <algorithm> |
18 | | #include <cstddef> |
19 | | #include <cstdint> |
20 | | #include <stack> |
21 | | #include <vector> |
22 | | |
23 | | #include "cel/expr/syntax.pb.h" |
24 | | #include "google/protobuf/struct.pb.h" |
25 | | #include "absl/base/attributes.h" |
26 | | #include "absl/base/nullability.h" |
27 | | #include "absl/functional/overload.h" |
28 | | #include "absl/status/status.h" |
29 | | #include "absl/strings/str_cat.h" |
30 | | #include "absl/types/variant.h" |
31 | | #include "common/ast/constant_proto.h" |
32 | | #include "common/constant.h" |
33 | | #include "common/expr.h" |
34 | | #include "internal/status_macros.h" |
35 | | |
36 | | namespace cel::ast_internal { |
37 | | |
38 | | namespace { |
39 | | |
40 | | using ExprProto = cel::expr::Expr; |
41 | | using ConstantProto = cel::expr::Constant; |
42 | | using StructExprProto = cel::expr::Expr::CreateStruct; |
43 | | |
44 | | class ExprToProtoState final { |
45 | | private: |
46 | | struct Frame final { |
47 | | const Expr* absl_nonnull expr; |
48 | | cel::expr::Expr* absl_nonnull proto; |
49 | | }; |
50 | | |
51 | | public: |
52 | | absl::Status ExprToProto(const Expr& expr, |
53 | 1.32k | cel::expr::Expr* absl_nonnull proto) { |
54 | 1.32k | Push(expr, proto); |
55 | 1.32k | Frame frame; |
56 | 1.41M | while (Pop(frame)) { |
57 | 1.41M | CEL_RETURN_IF_ERROR(ExprToProtoImpl(*frame.expr, frame.proto)); |
58 | 1.41M | } |
59 | 1.32k | return absl::OkStatus(); |
60 | 1.32k | } |
61 | | |
62 | | private: |
63 | | absl::Status ExprToProtoImpl(const Expr& expr, |
64 | 1.41M | cel::expr::Expr* absl_nonnull proto) { |
65 | 1.41M | return absl::visit( |
66 | 1.41M | absl::Overload( |
67 | 1.41M | [&expr, proto](const UnspecifiedExpr&) -> absl::Status { |
68 | 0 | proto->Clear(); |
69 | 0 | proto->set_id(expr.id()); |
70 | 0 | return absl::OkStatus(); |
71 | 0 | }, |
72 | 1.41M | [this, &expr, proto](const Constant& const_expr) -> absl::Status { |
73 | 612k | return ConstExprToProto(expr, const_expr, proto); |
74 | 612k | }, |
75 | 1.41M | [this, &expr, proto](const IdentExpr& ident_expr) -> absl::Status { |
76 | 381k | return IdentExprToProto(expr, ident_expr, proto); |
77 | 381k | }, |
78 | 1.41M | [this, &expr, |
79 | 1.41M | proto](const SelectExpr& select_expr) -> absl::Status { |
80 | 752 | return SelectExprToProto(expr, select_expr, proto); |
81 | 752 | }, |
82 | 1.41M | [this, &expr, proto](const CallExpr& call_expr) -> absl::Status { |
83 | 414k | return CallExprToProto(expr, call_expr, proto); |
84 | 414k | }, |
85 | 1.41M | [this, &expr, proto](const ListExpr& list_expr) -> absl::Status { |
86 | 474 | return ListExprToProto(expr, list_expr, proto); |
87 | 474 | }, |
88 | 1.41M | [this, &expr, |
89 | 1.41M | proto](const StructExpr& struct_expr) -> absl::Status { |
90 | 145 | return StructExprToProto(expr, struct_expr, proto); |
91 | 145 | }, |
92 | 1.41M | [this, &expr, proto](const MapExpr& map_expr) -> absl::Status { |
93 | 189 | return MapExprToProto(expr, map_expr, proto); |
94 | 189 | }, |
95 | 1.41M | [this, &expr, proto]( |
96 | 1.41M | const ComprehensionExpr& comprehension_expr) -> absl::Status { |
97 | 221 | return ComprehensionExprToProto(expr, comprehension_expr, proto); |
98 | 221 | }), |
99 | 1.41M | expr.kind()); |
100 | 1.41M | } |
101 | | |
102 | | absl::Status ConstExprToProto(const Expr& expr, const Constant& const_expr, |
103 | 612k | ExprProto* absl_nonnull proto) { |
104 | 612k | proto->Clear(); |
105 | 612k | proto->set_id(expr.id()); |
106 | 612k | return ConstantToProto(const_expr, proto->mutable_const_expr()); |
107 | 612k | } |
108 | | |
109 | | absl::Status IdentExprToProto(const Expr& expr, const IdentExpr& ident_expr, |
110 | 381k | ExprProto* absl_nonnull proto) { |
111 | 381k | proto->Clear(); |
112 | 381k | auto* ident_proto = proto->mutable_ident_expr(); |
113 | 381k | proto->set_id(expr.id()); |
114 | 381k | ident_proto->set_name(ident_expr.name()); |
115 | 381k | return absl::OkStatus(); |
116 | 381k | } |
117 | | |
118 | | absl::Status SelectExprToProto(const Expr& expr, |
119 | | const SelectExpr& select_expr, |
120 | 752 | ExprProto* absl_nonnull proto) { |
121 | 752 | proto->Clear(); |
122 | 752 | auto* select_proto = proto->mutable_select_expr(); |
123 | 752 | proto->set_id(expr.id()); |
124 | 752 | if (select_expr.has_operand()) { |
125 | 752 | Push(select_expr.operand(), select_proto->mutable_operand()); |
126 | 752 | } |
127 | 752 | select_proto->set_field(select_expr.field()); |
128 | 752 | select_proto->set_test_only(select_expr.test_only()); |
129 | 752 | return absl::OkStatus(); |
130 | 752 | } |
131 | | |
132 | | absl::Status CallExprToProto(const Expr& expr, const CallExpr& call_expr, |
133 | 414k | ExprProto* absl_nonnull proto) { |
134 | 414k | proto->Clear(); |
135 | 414k | auto* call_proto = proto->mutable_call_expr(); |
136 | 414k | proto->set_id(expr.id()); |
137 | 414k | if (call_expr.has_target()) { |
138 | 197 | Push(call_expr.target(), call_proto->mutable_target()); |
139 | 197 | } |
140 | 414k | call_proto->set_function(call_expr.function()); |
141 | 414k | if (!call_expr.args().empty()) { |
142 | 414k | call_proto->mutable_args()->Reserve( |
143 | 414k | static_cast<int>(call_expr.args().size())); |
144 | 797k | for (const auto& argument : call_expr.args()) { |
145 | 797k | Push(argument, call_proto->add_args()); |
146 | 797k | } |
147 | 414k | } |
148 | 414k | return absl::OkStatus(); |
149 | 414k | } |
150 | | |
151 | | absl::Status ListExprToProto(const Expr& expr, const ListExpr& list_expr, |
152 | 474 | ExprProto* absl_nonnull proto) { |
153 | 474 | proto->Clear(); |
154 | 474 | auto* list_proto = proto->mutable_list_expr(); |
155 | 474 | proto->set_id(expr.id()); |
156 | 474 | if (!list_expr.elements().empty()) { |
157 | 417 | list_proto->mutable_elements()->Reserve( |
158 | 417 | static_cast<int>(list_expr.elements().size())); |
159 | 886 | for (size_t i = 0; i < list_expr.elements().size(); ++i) { |
160 | 469 | const auto& element_expr = list_expr.elements()[i]; |
161 | 469 | auto* element_proto = list_proto->add_elements(); |
162 | 469 | if (element_expr.has_expr()) { |
163 | 469 | Push(element_expr.expr(), element_proto); |
164 | 469 | } |
165 | 469 | if (element_expr.optional()) { |
166 | 0 | list_proto->add_optional_indices(static_cast<int32_t>(i)); |
167 | 0 | } |
168 | 469 | } |
169 | 417 | } |
170 | 474 | return absl::OkStatus(); |
171 | 474 | } |
172 | | |
173 | | absl::Status StructExprToProto(const Expr& expr, |
174 | | const StructExpr& struct_expr, |
175 | 145 | ExprProto* absl_nonnull proto) { |
176 | 145 | proto->Clear(); |
177 | 145 | auto* struct_proto = proto->mutable_struct_expr(); |
178 | 145 | proto->set_id(expr.id()); |
179 | 145 | struct_proto->set_message_name(struct_expr.name()); |
180 | 145 | if (!struct_expr.fields().empty()) { |
181 | 17 | struct_proto->mutable_entries()->Reserve( |
182 | 17 | static_cast<int>(struct_expr.fields().size())); |
183 | 181 | for (const auto& field_expr : struct_expr.fields()) { |
184 | 181 | auto* field_proto = struct_proto->add_entries(); |
185 | 181 | field_proto->set_id(field_expr.id()); |
186 | 181 | field_proto->set_field_key(field_expr.name()); |
187 | 181 | if (field_expr.has_value()) { |
188 | 181 | Push(field_expr.value(), field_proto->mutable_value()); |
189 | 181 | } |
190 | 181 | if (field_expr.optional()) { |
191 | 0 | field_proto->set_optional_entry(true); |
192 | 0 | } |
193 | 181 | } |
194 | 17 | } |
195 | 145 | return absl::OkStatus(); |
196 | 145 | } |
197 | | |
198 | | absl::Status MapExprToProto(const Expr& expr, const MapExpr& map_expr, |
199 | 189 | ExprProto* absl_nonnull proto) { |
200 | 189 | proto->Clear(); |
201 | 189 | auto* map_proto = proto->mutable_struct_expr(); |
202 | 189 | proto->set_id(expr.id()); |
203 | 189 | if (!map_expr.entries().empty()) { |
204 | 70 | map_proto->mutable_entries()->Reserve( |
205 | 70 | static_cast<int>(map_expr.entries().size())); |
206 | 304k | for (const auto& entry_expr : map_expr.entries()) { |
207 | 304k | auto* entry_proto = map_proto->add_entries(); |
208 | 304k | entry_proto->set_id(entry_expr.id()); |
209 | 304k | if (entry_expr.has_key()) { |
210 | 304k | Push(entry_expr.key(), entry_proto->mutable_map_key()); |
211 | 304k | } |
212 | 304k | if (entry_expr.has_value()) { |
213 | 304k | Push(entry_expr.value(), entry_proto->mutable_value()); |
214 | 304k | } |
215 | 304k | if (entry_expr.optional()) { |
216 | 0 | entry_proto->set_optional_entry(true); |
217 | 0 | } |
218 | 304k | } |
219 | 70 | } |
220 | 189 | return absl::OkStatus(); |
221 | 189 | } |
222 | | |
223 | | absl::Status ComprehensionExprToProto( |
224 | | const Expr& expr, const ComprehensionExpr& comprehension_expr, |
225 | 221 | ExprProto* absl_nonnull proto) { |
226 | 221 | proto->Clear(); |
227 | 221 | auto* comprehension_proto = proto->mutable_comprehension_expr(); |
228 | 221 | proto->set_id(expr.id()); |
229 | 221 | comprehension_proto->set_iter_var(comprehension_expr.iter_var()); |
230 | 221 | comprehension_proto->set_iter_var2(comprehension_expr.iter_var2()); |
231 | 221 | if (comprehension_expr.has_iter_range()) { |
232 | 221 | Push(comprehension_expr.iter_range(), |
233 | 221 | comprehension_proto->mutable_iter_range()); |
234 | 221 | } |
235 | 221 | comprehension_proto->set_accu_var(comprehension_expr.accu_var()); |
236 | 221 | if (comprehension_expr.has_accu_init()) { |
237 | 221 | Push(comprehension_expr.accu_init(), |
238 | 221 | comprehension_proto->mutable_accu_init()); |
239 | 221 | } |
240 | 221 | if (comprehension_expr.has_loop_condition()) { |
241 | 221 | Push(comprehension_expr.loop_condition(), |
242 | 221 | comprehension_proto->mutable_loop_condition()); |
243 | 221 | } |
244 | 221 | if (comprehension_expr.has_loop_step()) { |
245 | 221 | Push(comprehension_expr.loop_step(), |
246 | 221 | comprehension_proto->mutable_loop_step()); |
247 | 221 | } |
248 | 221 | if (comprehension_expr.has_result()) { |
249 | 221 | Push(comprehension_expr.result(), comprehension_proto->mutable_result()); |
250 | 221 | } |
251 | 221 | return absl::OkStatus(); |
252 | 221 | } |
253 | | |
254 | 1.41M | void Push(const Expr& expr, ExprProto* absl_nonnull proto) { |
255 | 1.41M | frames_.push(Frame{&expr, proto}); |
256 | 1.41M | } |
257 | | |
258 | 1.41M | bool Pop(Frame& frame) { |
259 | 1.41M | if (frames_.empty()) { |
260 | 1.32k | return false; |
261 | 1.32k | } |
262 | 1.41M | frame = frames_.top(); |
263 | 1.41M | frames_.pop(); |
264 | 1.41M | return true; |
265 | 1.41M | } |
266 | | |
267 | | std::stack<Frame, std::vector<Frame>> frames_; |
268 | | }; |
269 | | |
270 | | class ExprFromProtoState final { |
271 | | private: |
272 | | struct Frame final { |
273 | | const ExprProto* absl_nonnull proto; |
274 | | Expr* absl_nonnull expr; |
275 | | }; |
276 | | |
277 | | public: |
278 | 0 | absl::Status ExprFromProto(const ExprProto& proto, Expr& expr) { |
279 | 0 | Push(proto, expr); |
280 | 0 | Frame frame; |
281 | 0 | while (Pop(frame)) { |
282 | 0 | CEL_RETURN_IF_ERROR(ExprFromProtoImpl(*frame.proto, *frame.expr)); |
283 | 0 | } |
284 | 0 | return absl::OkStatus(); |
285 | 0 | } |
286 | | |
287 | | private: |
288 | 0 | absl::Status ExprFromProtoImpl(const ExprProto& proto, Expr& expr) { |
289 | 0 | switch (proto.expr_kind_case()) { |
290 | 0 | case ExprProto::EXPR_KIND_NOT_SET: |
291 | 0 | expr.Clear(); |
292 | 0 | expr.set_id(proto.id()); |
293 | 0 | return absl::OkStatus(); |
294 | 0 | case ExprProto::kConstExpr: |
295 | 0 | return ConstExprFromProto(proto, proto.const_expr(), expr); |
296 | 0 | case ExprProto::kIdentExpr: |
297 | 0 | return IdentExprFromProto(proto, proto.ident_expr(), expr); |
298 | 0 | case ExprProto::kSelectExpr: |
299 | 0 | return SelectExprFromProto(proto, proto.select_expr(), expr); |
300 | 0 | case ExprProto::kCallExpr: |
301 | 0 | return CallExprFromProto(proto, proto.call_expr(), expr); |
302 | 0 | case ExprProto::kListExpr: |
303 | 0 | return ListExprFromProto(proto, proto.list_expr(), expr); |
304 | 0 | case ExprProto::kStructExpr: |
305 | 0 | if (proto.struct_expr().message_name().empty()) { |
306 | 0 | return MapExprFromProto(proto, proto.struct_expr(), expr); |
307 | 0 | } |
308 | 0 | return StructExprFromProto(proto, proto.struct_expr(), expr); |
309 | 0 | case ExprProto::kComprehensionExpr: |
310 | 0 | return ComprehensionExprFromProto(proto, proto.comprehension_expr(), |
311 | 0 | expr); |
312 | 0 | default: |
313 | 0 | return absl::InvalidArgumentError( |
314 | 0 | absl::StrCat("unexpected ExprKindCase: ", |
315 | 0 | static_cast<int>(proto.expr_kind_case()))); |
316 | 0 | } |
317 | 0 | } |
318 | | |
319 | | absl::Status ConstExprFromProto(const ExprProto& proto, |
320 | | const ConstantProto& const_proto, |
321 | 0 | Expr& expr) { |
322 | 0 | expr.Clear(); |
323 | 0 | expr.set_id(proto.id()); |
324 | 0 | return ConstantFromProto(const_proto, expr.mutable_const_expr()); |
325 | 0 | } |
326 | | |
327 | | absl::Status IdentExprFromProto(const ExprProto& proto, |
328 | | const ExprProto::Ident& ident_proto, |
329 | 0 | Expr& expr) { |
330 | 0 | expr.Clear(); |
331 | 0 | expr.set_id(proto.id()); |
332 | 0 | auto& ident_expr = expr.mutable_ident_expr(); |
333 | 0 | ident_expr.set_name(ident_proto.name()); |
334 | 0 | return absl::OkStatus(); |
335 | 0 | } |
336 | | |
337 | | absl::Status SelectExprFromProto(const ExprProto& proto, |
338 | | const ExprProto::Select& select_proto, |
339 | 0 | Expr& expr) { |
340 | 0 | expr.Clear(); |
341 | 0 | expr.set_id(proto.id()); |
342 | 0 | auto& select_expr = expr.mutable_select_expr(); |
343 | 0 | if (select_proto.has_operand()) { |
344 | 0 | Push(select_proto.operand(), select_expr.mutable_operand()); |
345 | 0 | } |
346 | 0 | select_expr.set_field(select_proto.field()); |
347 | 0 | select_expr.set_test_only(select_proto.test_only()); |
348 | 0 | return absl::OkStatus(); |
349 | 0 | } |
350 | | |
351 | | absl::Status CallExprFromProto(const ExprProto& proto, |
352 | | const ExprProto::Call& call_proto, |
353 | 0 | Expr& expr) { |
354 | 0 | expr.Clear(); |
355 | 0 | expr.set_id(proto.id()); |
356 | 0 | auto& call_expr = expr.mutable_call_expr(); |
357 | 0 | call_expr.set_function(call_proto.function()); |
358 | 0 | if (call_proto.has_target()) { |
359 | 0 | Push(call_proto.target(), call_expr.mutable_target()); |
360 | 0 | } |
361 | 0 | call_expr.mutable_args().reserve( |
362 | 0 | static_cast<size_t>(call_proto.args().size())); |
363 | 0 | for (const auto& argument_proto : call_proto.args()) { |
364 | 0 | Push(argument_proto, call_expr.add_args()); |
365 | 0 | } |
366 | 0 | return absl::OkStatus(); |
367 | 0 | } |
368 | | |
369 | | absl::Status ListExprFromProto(const ExprProto& proto, |
370 | | const ExprProto::CreateList& list_proto, |
371 | 0 | Expr& expr) { |
372 | 0 | expr.Clear(); |
373 | 0 | expr.set_id(proto.id()); |
374 | 0 | auto& list_expr = expr.mutable_list_expr(); |
375 | 0 | list_expr.mutable_elements().reserve( |
376 | 0 | static_cast<size_t>(list_proto.elements().size())); |
377 | 0 | for (int i = 0; i < list_proto.elements().size(); ++i) { |
378 | 0 | const auto& element_proto = list_proto.elements()[i]; |
379 | 0 | auto& element_expr = list_expr.add_elements(); |
380 | 0 | Push(element_proto, element_expr.mutable_expr()); |
381 | 0 | const auto& optional_indicies_proto = list_proto.optional_indices(); |
382 | 0 | element_expr.set_optional(std::find(optional_indicies_proto.begin(), |
383 | 0 | optional_indicies_proto.end(), |
384 | 0 | i) != optional_indicies_proto.end()); |
385 | 0 | } |
386 | 0 | return absl::OkStatus(); |
387 | 0 | } |
388 | | |
389 | | absl::Status StructExprFromProto(const ExprProto& proto, |
390 | | const StructExprProto& struct_proto, |
391 | 0 | Expr& expr) { |
392 | 0 | expr.Clear(); |
393 | 0 | expr.set_id(proto.id()); |
394 | 0 | auto& struct_expr = expr.mutable_struct_expr(); |
395 | 0 | struct_expr.set_name(struct_proto.message_name()); |
396 | 0 | struct_expr.mutable_fields().reserve( |
397 | 0 | static_cast<size_t>(struct_proto.entries().size())); |
398 | 0 | for (const auto& field_proto : struct_proto.entries()) { |
399 | 0 | switch (field_proto.key_kind_case()) { |
400 | 0 | case StructExprProto::Entry::KEY_KIND_NOT_SET: |
401 | 0 | ABSL_FALLTHROUGH_INTENDED; |
402 | 0 | case StructExprProto::Entry::kFieldKey: |
403 | 0 | break; |
404 | 0 | case StructExprProto::Entry::kMapKey: |
405 | 0 | return absl::InvalidArgumentError("encountered map entry in struct"); |
406 | 0 | default: |
407 | 0 | return absl::InvalidArgumentError(absl::StrCat( |
408 | 0 | "unexpected struct field kind: ", field_proto.key_kind_case())); |
409 | 0 | } |
410 | 0 | auto& field_expr = struct_expr.add_fields(); |
411 | 0 | field_expr.set_id(field_proto.id()); |
412 | 0 | field_expr.set_name(field_proto.field_key()); |
413 | 0 | if (field_proto.has_value()) { |
414 | 0 | Push(field_proto.value(), field_expr.mutable_value()); |
415 | 0 | } |
416 | 0 | field_expr.set_optional(field_proto.optional_entry()); |
417 | 0 | } |
418 | 0 | return absl::OkStatus(); |
419 | 0 | } |
420 | | |
421 | | absl::Status MapExprFromProto(const ExprProto& proto, |
422 | | const ExprProto::CreateStruct& map_proto, |
423 | 0 | Expr& expr) { |
424 | 0 | expr.Clear(); |
425 | 0 | expr.set_id(proto.id()); |
426 | 0 | auto& map_expr = expr.mutable_map_expr(); |
427 | 0 | map_expr.mutable_entries().reserve( |
428 | 0 | static_cast<size_t>(map_proto.entries().size())); |
429 | 0 | for (const auto& entry_proto : map_proto.entries()) { |
430 | 0 | switch (entry_proto.key_kind_case()) { |
431 | 0 | case StructExprProto::Entry::KEY_KIND_NOT_SET: |
432 | 0 | ABSL_FALLTHROUGH_INTENDED; |
433 | 0 | case StructExprProto::Entry::kMapKey: |
434 | 0 | break; |
435 | 0 | case StructExprProto::Entry::kFieldKey: |
436 | 0 | return absl::InvalidArgumentError("encountered struct field in map"); |
437 | 0 | default: |
438 | 0 | return absl::InvalidArgumentError(absl::StrCat( |
439 | 0 | "unexpected map entry kind: ", entry_proto.key_kind_case())); |
440 | 0 | } |
441 | 0 | auto& entry_expr = map_expr.add_entries(); |
442 | 0 | entry_expr.set_id(entry_proto.id()); |
443 | 0 | if (entry_proto.has_map_key()) { |
444 | 0 | Push(entry_proto.map_key(), entry_expr.mutable_key()); |
445 | 0 | } |
446 | 0 | if (entry_proto.has_value()) { |
447 | 0 | Push(entry_proto.value(), entry_expr.mutable_value()); |
448 | 0 | } |
449 | 0 | entry_expr.set_optional(entry_proto.optional_entry()); |
450 | 0 | } |
451 | 0 | return absl::OkStatus(); |
452 | 0 | } |
453 | | |
454 | | absl::Status ComprehensionExprFromProto( |
455 | | const ExprProto& proto, |
456 | 0 | const ExprProto::Comprehension& comprehension_proto, Expr& expr) { |
457 | 0 | expr.Clear(); |
458 | 0 | expr.set_id(proto.id()); |
459 | 0 | auto& comprehension_expr = expr.mutable_comprehension_expr(); |
460 | 0 | comprehension_expr.set_iter_var(comprehension_proto.iter_var()); |
461 | 0 | comprehension_expr.set_iter_var2(comprehension_proto.iter_var2()); |
462 | 0 | comprehension_expr.set_accu_var(comprehension_proto.accu_var()); |
463 | 0 | if (comprehension_proto.has_iter_range()) { |
464 | 0 | Push(comprehension_proto.iter_range(), |
465 | 0 | comprehension_expr.mutable_iter_range()); |
466 | 0 | } |
467 | 0 | if (comprehension_proto.has_accu_init()) { |
468 | 0 | Push(comprehension_proto.accu_init(), |
469 | 0 | comprehension_expr.mutable_accu_init()); |
470 | 0 | } |
471 | 0 | if (comprehension_proto.has_loop_condition()) { |
472 | 0 | Push(comprehension_proto.loop_condition(), |
473 | 0 | comprehension_expr.mutable_loop_condition()); |
474 | 0 | } |
475 | 0 | if (comprehension_proto.has_loop_step()) { |
476 | 0 | Push(comprehension_proto.loop_step(), |
477 | 0 | comprehension_expr.mutable_loop_step()); |
478 | 0 | } |
479 | 0 | if (comprehension_proto.has_result()) { |
480 | 0 | Push(comprehension_proto.result(), comprehension_expr.mutable_result()); |
481 | 0 | } |
482 | 0 | return absl::OkStatus(); |
483 | 0 | } |
484 | | |
485 | 0 | void Push(const ExprProto& proto, Expr& expr) { |
486 | 0 | frames_.push(Frame{&proto, &expr}); |
487 | 0 | } |
488 | | |
489 | 0 | bool Pop(Frame& frame) { |
490 | 0 | if (frames_.empty()) { |
491 | 0 | return false; |
492 | 0 | } |
493 | 0 | frame = frames_.top(); |
494 | 0 | frames_.pop(); |
495 | 0 | return true; |
496 | 0 | } |
497 | | |
498 | | std::stack<Frame, std::vector<Frame>> frames_; |
499 | | }; |
500 | | |
501 | | } // namespace |
502 | | |
503 | | absl::Status ExprToProto(const Expr& expr, |
504 | 1.32k | cel::expr::Expr* absl_nonnull proto) { |
505 | 1.32k | ExprToProtoState state; |
506 | 1.32k | return state.ExprToProto(expr, proto); |
507 | 1.32k | } |
508 | | |
509 | 0 | absl::Status ExprFromProto(const cel::expr::Expr& proto, Expr& expr) { |
510 | 0 | ExprFromProtoState state; |
511 | 0 | return state.ExprFromProto(proto, expr); |
512 | 0 | } |
513 | | |
514 | | } // namespace cel::ast_internal |