Skip to content

Commit 5cc767d

Browse files
jnthntatumcopybara-github
authored andcommitted
Add to proto function for cel::Ast.
PiperOrigin-RevId: 580013592
1 parent ee70ab2 commit 5cc767d

15 files changed

Lines changed: 1245 additions & 188 deletions

File tree

base/ast_internal/BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ cc_library(
3030
"//base:ast",
3131
"//internal:casts",
3232
"@com_google_absl//absl/container:flat_hash_map",
33+
"@com_google_absl//absl/strings:string_view",
3334
],
3435
)
3536

@@ -51,6 +52,7 @@ cc_library(
5152
"expr.h",
5253
],
5354
deps = [
55+
"//internal:overloaded",
5456
"@com_google_absl//absl/container:flat_hash_map",
5557
"@com_google_absl//absl/time",
5658
"@com_google_absl//absl/types:variant",

base/ast_internal/ast_impl.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,12 @@ const Reference* AstImpl::GetReference(int64_t expr_id) const {
4646
return &iter->second;
4747
}
4848

49+
AstImpl AstImpl::DeepCopy() const {
50+
AstImpl copy(root_expr_.DeepCopy(), source_info_.DeepCopy());
51+
copy.type_map_ = type_map_;
52+
copy.reference_map_ = reference_map_;
53+
copy.is_checked_ = is_checked_;
54+
return copy;
55+
}
56+
4957
} // namespace cel::ast_internal

base/ast_internal/ast_impl.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@
1616
#define THIRD_PARTY_CEL_CPP_BASE_AST_INTERNAL_AST_IMPL_H_
1717

1818
#include <cstdint>
19+
#include <string>
1920
#include <utility>
2021

2122
#include "absl/container/flat_hash_map.h"
23+
#include "absl/strings/string_view.h"
2224
#include "base/ast.h"
2325
#include "base/ast_internal/expr.h"
2426
#include "internal/casts.h"
@@ -49,6 +51,12 @@ class AstImpl : public Ast {
4951
return cel::internal::down_cast<const AstImpl*>(ast);
5052
}
5153

54+
// Move-only
55+
AstImpl(const AstImpl& other) = delete;
56+
AstImpl& operator=(const AstImpl& other) = delete;
57+
AstImpl(AstImpl&& other) = default;
58+
AstImpl& operator=(AstImpl&& other) = default;
59+
5260
explicit AstImpl(Expr expr, SourceInfo source_info)
5361
: root_expr_(std::move(expr)),
5462
source_info_(std::move(source_info)),
@@ -64,6 +72,7 @@ class AstImpl : public Ast {
6472
source_info_(std::move(expr.mutable_source_info())),
6573
reference_map_(std::move(expr.mutable_reference_map())),
6674
type_map_(std::move(expr.mutable_type_map())),
75+
expr_version_(std::move(expr.mutable_expr_version())),
6776
is_checked_(true) {}
6877

6978
// Implement public Ast APIs.
@@ -92,11 +101,16 @@ class AstImpl : public Ast {
92101
return type_map_;
93102
}
94103

104+
absl::string_view expr_version() const { return expr_version_; }
105+
106+
AstImpl DeepCopy() const;
107+
95108
private:
96109
Expr root_expr_;
97110
SourceInfo source_info_;
98111
absl::flat_hash_map<int64_t, Reference> reference_map_;
99112
absl::flat_hash_map<int64_t, Type> type_map_;
113+
std::string expr_version_;
100114
bool is_checked_;
101115
};
102116

base/ast_internal/ast_impl_test.cc

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,5 +128,45 @@ TEST(AstImpl, CheckedExprCtor) {
128128
EXPECT_EQ(ast_impl.source_info().syntax_version(), "1.0");
129129
}
130130

131+
TEST(AstImpl, CheckedExprDeepCopy) {
132+
CheckedExpr expr;
133+
auto& root = expr.mutable_expr();
134+
root.set_id(3);
135+
root.mutable_call_expr().set_function("_==_");
136+
root.mutable_call_expr().mutable_args().resize(2);
137+
auto& lhs = root.mutable_call_expr().mutable_args()[0];
138+
auto& rhs = root.mutable_call_expr().mutable_args()[1];
139+
expr.mutable_type_map()[3] = Type(PrimitiveType::kBool);
140+
141+
lhs.mutable_ident_expr().set_name("int_value");
142+
lhs.set_id(1);
143+
Reference ref;
144+
ref.set_name("com.int_value");
145+
expr.mutable_reference_map()[1] = std::move(ref);
146+
expr.mutable_type_map()[1] = Type(PrimitiveType::kInt64);
147+
148+
rhs.mutable_const_expr().set_int64_value(2);
149+
rhs.set_id(2);
150+
expr.mutable_type_map()[2] = Type(PrimitiveType::kInt64);
151+
expr.mutable_source_info().set_syntax_version("1.0");
152+
153+
AstImpl ast_impl(std::move(expr));
154+
AstImpl ast_impl_copy = ast_impl.DeepCopy();
155+
Ast& ast = ast_impl_copy;
156+
157+
ASSERT_TRUE(ast.IsChecked());
158+
EXPECT_EQ(ast_impl_copy.GetType(1), Type(PrimitiveType::kInt64));
159+
EXPECT_THAT(ast_impl_copy.GetReference(1),
160+
Pointee(Truly([](const Reference& arg) {
161+
return arg.name() == "com.int_value";
162+
})));
163+
EXPECT_EQ(ast_impl_copy.GetReturnType(), Type(PrimitiveType::kBool));
164+
EXPECT_TRUE(ast_impl_copy.root_expr().has_call_expr());
165+
EXPECT_EQ(ast_impl_copy.root_expr().call_expr().function(), "_==_");
166+
EXPECT_EQ(ast_impl_copy.root_expr().id(), 3);
167+
EXPECT_EQ(ast_impl_copy.source_info().syntax_version(), "1.0");
168+
EXPECT_EQ(ast_impl.root_expr(), ast_impl_copy.root_expr());
169+
}
170+
131171
} // namespace
132172
} // namespace cel::ast_internal

base/ast_internal/expr.cc

Lines changed: 156 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,155 @@
1515
#include "base/ast_internal/expr.h"
1616

1717
#include <memory>
18+
#include <stack>
19+
#include <vector>
20+
21+
#include "absl/types/variant.h"
22+
#include "internal/overloaded.h"
1823

1924
namespace cel::ast_internal {
2025

2126
namespace {
27+
2228
const Expr& default_expr() {
2329
static Expr* expr = new Expr();
2430
return *expr;
2531
}
32+
33+
const Type& default_type() {
34+
static Type* type = new Type();
35+
return *type;
36+
}
37+
38+
struct CopyRecord {
39+
const Expr* src;
40+
Expr* dest;
41+
};
42+
43+
void CopyNode(const Expr& src, std::stack<CopyRecord>& records, Expr& dest) {
44+
dest.set_id(src.id());
45+
46+
const auto& src_kind = src.expr_kind();
47+
absl::visit(
48+
cel::internal::Overloaded{
49+
[&](const Constant& constant) {
50+
dest.mutable_expr_kind() = constant;
51+
},
52+
[&](const Ident& ident) { dest.mutable_expr_kind() = ident; },
53+
[&](const Select& select) {
54+
auto& dest_select = dest.mutable_select_expr();
55+
dest_select.set_field(select.field());
56+
dest_select.set_test_only(select.test_only());
57+
records.push({&select.operand(), &dest_select.mutable_operand()});
58+
},
59+
[&](const Call& call) {
60+
auto& dest_call = dest.mutable_call_expr();
61+
dest_call.set_function(call.function());
62+
if (call.has_target()) {
63+
records.push({&call.target(), &dest_call.mutable_target()});
64+
}
65+
// pointer stability is guaranteed since the vector itself won't
66+
// change anywhere else in the copy routine.
67+
dest_call.mutable_args() = std::vector<Expr>(call.args().size());
68+
for (int i = 0; i < call.args().size(); ++i) {
69+
records.push({&call.args()[i], &dest_call.mutable_args()[i]});
70+
}
71+
},
72+
[&](const CreateList& create_list) {
73+
auto& dest_create_list = dest.mutable_list_expr();
74+
dest_create_list.optional_indices() =
75+
create_list.optional_indices();
76+
77+
// pointer stability is guaranteed since the vector itself won't
78+
// change anywhere else in the copy routine.
79+
dest_create_list.mutable_elements() =
80+
std::vector<Expr>(create_list.elements().size());
81+
for (int i = 0; i < create_list.elements().size(); ++i) {
82+
records.push({&create_list.elements()[i],
83+
&dest_create_list.mutable_elements()[i]});
84+
}
85+
},
86+
[&](const Comprehension& comprehension) {
87+
auto& dest_comprehension = dest.mutable_comprehension_expr();
88+
dest_comprehension.set_iter_var(comprehension.iter_var());
89+
dest_comprehension.set_accu_var(comprehension.accu_var());
90+
records.push({&comprehension.iter_range(),
91+
&dest_comprehension.mutable_iter_range()});
92+
records.push({&comprehension.accu_init(),
93+
&dest_comprehension.mutable_accu_init()});
94+
records.push({&comprehension.loop_condition(),
95+
&dest_comprehension.mutable_loop_condition()});
96+
records.push({&comprehension.loop_step(),
97+
&dest_comprehension.mutable_loop_step()});
98+
records.push({&comprehension.result(),
99+
&dest_comprehension.mutable_result()});
100+
},
101+
[&](const CreateStruct& struct_expr) {
102+
auto& dest_struct_expr = dest.mutable_struct_expr();
103+
dest_struct_expr.set_message_name(struct_expr.message_name());
104+
105+
dest_struct_expr.mutable_entries() =
106+
std::vector<CreateStruct::Entry>(struct_expr.entries().size());
107+
for (int i = 0; i < struct_expr.entries().size(); ++i) {
108+
auto& dest_entry = dest_struct_expr.mutable_entries()[i];
109+
const auto& entry = struct_expr.entries()[i];
110+
111+
dest_entry.set_id(entry.id());
112+
dest_entry.set_optional_entry(entry.optional_entry());
113+
records.push({&entry.value(), &dest_entry.mutable_value()});
114+
115+
if (entry.has_field_key()) {
116+
dest_entry.set_field_key(entry.field_key());
117+
} else {
118+
records.push({&entry.map_key(), &dest_entry.mutable_map_key()});
119+
}
120+
}
121+
},
122+
[&](absl::monostate) {
123+
// unset expr kind, nothing todo.
124+
}},
125+
src_kind);
126+
}
127+
128+
TypeKind CopyImpl(const TypeKind& other) {
129+
return absl::visit(cel::internal::Overloaded{
130+
[](const std::unique_ptr<Type>& other) -> TypeKind {
131+
return std::make_unique<Type>(*other);
132+
},
133+
[](const auto& other) -> TypeKind {
134+
// Other variants define copy ctor.
135+
return other;
136+
}},
137+
other);
138+
}
139+
26140
} // namespace
27141

142+
Expr Expr::DeepCopy() const {
143+
Expr copy;
144+
std::stack<CopyRecord> records;
145+
records.push(CopyRecord{this, &copy});
146+
while (!records.empty()) {
147+
CopyRecord next = records.top();
148+
records.pop();
149+
CopyNode(*next.src, records, *next.dest);
150+
}
151+
return copy;
152+
}
153+
154+
SourceInfo SourceInfo::DeepCopy() const {
155+
SourceInfo copy;
156+
copy.location_ = location_;
157+
copy.syntax_version_ = syntax_version_;
158+
copy.line_offsets_ = line_offsets_;
159+
copy.positions_ = positions_;
160+
copy.macro_calls_.reserve(macro_calls_.size());
161+
for (auto it = macro_calls_.begin(); it != macro_calls_.end(); ++it) {
162+
copy.macro_calls_.insert_or_assign(it->first, it->second.DeepCopy());
163+
}
164+
return copy;
165+
}
166+
28167
const Expr& Select::operand() const {
29168
if (operand_ != nullptr) {
30169
return *operand_;
@@ -117,13 +256,6 @@ bool Comprehension::operator==(const Comprehension& other) const {
117256
loop_step() == other.loop_step() && result() == other.result();
118257
}
119258

120-
namespace {
121-
const Type& default_type() {
122-
static Type* type = new Type();
123-
return *type;
124-
}
125-
} // namespace
126-
127259
const Type& ListType::elem_type() const {
128260
if (elem_type_ != nullptr) {
129261
return *elem_type_;
@@ -172,4 +304,21 @@ const Type& Type::type() const {
172304
return default_type();
173305
}
174306

307+
Type::Type(const Type& other) : type_kind_(CopyImpl(other.type_kind_)) {}
308+
309+
Type& Type::operator=(const Type& other) {
310+
type_kind_ = CopyImpl(other.type_kind_);
311+
return *this;
312+
}
313+
314+
FunctionType::FunctionType(const FunctionType& other)
315+
: result_type_(std::make_unique<Type>(other.result_type())),
316+
arg_types_(other.arg_types()) {}
317+
318+
FunctionType& FunctionType::operator=(const FunctionType& other) {
319+
result_type_ = std::make_unique<Type>(other.result_type());
320+
arg_types_ = other.arg_types();
321+
return *this;
322+
}
323+
175324
} // namespace cel::ast_internal

0 commit comments

Comments
 (0)