Coverage Report

Created: 2025-11-29 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/proc/self/cwd/common/expr.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/expr.h"
16
17
#include <utility>
18
#include <vector>
19
20
#include "absl/base/no_destructor.h"
21
#include "absl/functional/overload.h"
22
#include "absl/types/variant.h"
23
#include "common/constant.h"
24
25
namespace cel {
26
27
namespace {
28
29
struct CopyStackRecord {
30
  const Expr* src;
31
  Expr* dst;
32
};
33
34
0
void CopyNode(CopyStackRecord element, std::vector<CopyStackRecord>& stack) {
35
0
  const Expr* src = element.src;
36
0
  Expr* dst = element.dst;
37
0
  dst->set_id(src->id());
38
0
  absl::visit(
39
0
      absl::Overload(
40
0
          [=](const UnspecifiedExpr&) {
41
0
            dst->mutable_kind().emplace<UnspecifiedExpr>();
42
0
          },
43
0
          [=](const IdentExpr& i) {
44
0
            dst->mutable_ident_expr().set_name(i.name());
45
0
          },
46
0
          [=](const Constant& c) { dst->mutable_const_expr() = c; },
47
0
          [&](const SelectExpr& s) {
48
0
            dst->mutable_select_expr().set_field(s.field());
49
0
            dst->mutable_select_expr().set_test_only(s.test_only());
50
51
0
            if (s.has_operand()) {
52
0
              stack.push_back({&s.operand(),
53
0
                               &dst->mutable_select_expr().mutable_operand()});
54
0
            }
55
0
          },
56
0
          [&](const CallExpr& c) {
57
0
            dst->mutable_call_expr().set_function(c.function());
58
0
            if (c.has_target()) {
59
0
              stack.push_back(
60
0
                  {&c.target(), &dst->mutable_call_expr().mutable_target()});
61
0
            }
62
0
            dst->mutable_call_expr().mutable_args().resize(c.args().size());
63
0
            for (int i = 0; i < dst->mutable_call_expr().mutable_args().size();
64
0
                 ++i) {
65
0
              stack.push_back(
66
0
                  {&c.args()[i], &dst->mutable_call_expr().mutable_args()[i]});
67
0
            }
68
0
          },
69
0
          [&](const ListExpr& c) {
70
0
            auto& dst_list = dst->mutable_list_expr();
71
0
            dst_list.mutable_elements().resize(c.elements().size());
72
0
            for (int i = 0; i < src->list_expr().elements().size(); ++i) {
73
0
              dst_list.mutable_elements()[i].set_optional(
74
0
                  c.elements()[i].optional());
75
0
              stack.push_back({&c.elements()[i].expr(),
76
0
                               &dst_list.mutable_elements()[i].mutable_expr()});
77
0
            }
78
0
          },
79
0
          [&](const StructExpr& s) {
80
0
            auto& dst_struct = dst->mutable_struct_expr();
81
0
            dst_struct.mutable_fields().resize(s.fields().size());
82
0
            dst_struct.set_name(s.name());
83
0
            for (int i = 0; i < s.fields().size(); ++i) {
84
0
              dst_struct.mutable_fields()[i].set_optional(
85
0
                  s.fields()[i].optional());
86
0
              dst_struct.mutable_fields()[i].set_name(s.fields()[i].name());
87
0
              dst_struct.mutable_fields()[i].set_id(s.fields()[i].id());
88
0
              stack.push_back(
89
0
                  {&s.fields()[i].value(),
90
0
                   &dst_struct.mutable_fields()[i].mutable_value()});
91
0
            }
92
0
          },
93
0
          [&](const MapExpr& c) {
94
0
            auto& dst_map = dst->mutable_map_expr();
95
0
            dst_map.mutable_entries().resize(c.entries().size());
96
0
            for (int i = 0; i < c.entries().size(); ++i) {
97
0
              dst_map.mutable_entries()[i].set_optional(
98
0
                  c.entries()[i].optional());
99
0
              dst_map.mutable_entries()[i].set_id(c.entries()[i].id());
100
0
              stack.push_back({&c.entries()[i].key(),
101
0
                               &dst_map.mutable_entries()[i].mutable_key()});
102
0
              stack.push_back({&c.entries()[i].value(),
103
0
                               &dst_map.mutable_entries()[i].mutable_value()});
104
0
            }
105
0
          },
106
0
          [&](const ComprehensionExpr& c) {
107
0
            auto& dst_comprehension = dst->mutable_comprehension_expr();
108
0
            dst_comprehension.set_iter_var(c.iter_var());
109
0
            dst_comprehension.set_iter_var2(c.iter_var2());
110
0
            dst_comprehension.set_accu_var(c.accu_var());
111
0
            if (c.has_accu_init()) {
112
0
              stack.push_back(
113
0
                  {&c.accu_init(), &dst_comprehension.mutable_accu_init()});
114
0
            }
115
0
            if (c.has_iter_range()) {
116
0
              stack.push_back(
117
0
                  {&c.iter_range(), &dst_comprehension.mutable_iter_range()});
118
0
            }
119
0
            if (c.has_loop_condition()) {
120
0
              stack.push_back({&c.loop_condition(),
121
0
                               &dst_comprehension.mutable_loop_condition()});
122
0
            }
123
0
            if (c.has_loop_step()) {
124
0
              stack.push_back(
125
0
                  {&c.loop_step(), &dst_comprehension.mutable_loop_step()});
126
0
            }
127
0
            if (c.has_result()) {
128
0
              stack.push_back(
129
0
                  {&c.result(), &dst_comprehension.mutable_result()});
130
0
            }
131
0
          }),
132
0
      src->kind());
133
0
}
134
135
0
void CloneImpl(const Expr& expr, Expr& dst) {
136
0
  std::vector<CopyStackRecord> stack;
137
0
  stack.push_back({&expr, &dst});
138
0
  while (!stack.empty()) {
139
0
    CopyStackRecord element = stack.back();
140
0
    stack.pop_back();
141
0
    CopyNode(element, stack);
142
0
  }
143
0
}
144
145
}  // namespace
146
147
0
const UnspecifiedExpr& UnspecifiedExpr::default_instance() {
148
0
  static const absl::NoDestructor<UnspecifiedExpr> instance;
149
0
  return *instance;
150
0
}
151
152
0
const IdentExpr& IdentExpr::default_instance() {
153
0
  static const absl::NoDestructor<IdentExpr> instance;
154
0
  return *instance;
155
0
}
156
157
0
const SelectExpr& SelectExpr::default_instance() {
158
0
  static const absl::NoDestructor<SelectExpr> instance;
159
0
  return *instance;
160
0
}
161
162
0
const CallExpr& CallExpr::default_instance() {
163
0
  static const absl::NoDestructor<CallExpr> instance;
164
0
  return *instance;
165
0
}
166
167
0
const ListExpr& ListExpr::default_instance() {
168
0
  static const absl::NoDestructor<ListExpr> instance;
169
0
  return *instance;
170
0
}
171
172
0
const StructExpr& StructExpr::default_instance() {
173
0
  static const absl::NoDestructor<StructExpr> instance;
174
0
  return *instance;
175
0
}
176
177
0
const MapExpr& MapExpr::default_instance() {
178
0
  static const absl::NoDestructor<MapExpr> instance;
179
0
  return *instance;
180
0
}
181
182
0
const ComprehensionExpr& ComprehensionExpr::default_instance() {
183
0
  static const absl::NoDestructor<ComprehensionExpr> instance;
184
0
  return *instance;
185
0
}
186
187
0
const Expr& Expr::default_instance() {
188
0
  static const absl::NoDestructor<Expr> instance;
189
0
  return *instance;
190
0
}
191
192
0
Expr& Expr::operator=(const Expr& other) {
193
0
  if (this == &other) {
194
0
    return *this;
195
0
  }
196
0
  Expr tmp;
197
0
  CloneImpl(other, tmp);
198
0
  *this = std::move(tmp);
199
0
  return *this;
200
0
}
201
202
0
Expr::Expr(const Expr& other) { CloneImpl(other, *this); }
203
204
}  // namespace cel