|
15 | 15 | #include "base/ast_internal/expr.h" |
16 | 16 |
|
17 | 17 | #include <memory> |
| 18 | +#include <stack> |
| 19 | +#include <vector> |
| 20 | + |
| 21 | +#include "absl/types/variant.h" |
| 22 | +#include "internal/overloaded.h" |
18 | 23 |
|
19 | 24 | namespace cel::ast_internal { |
20 | 25 |
|
21 | 26 | namespace { |
| 27 | + |
22 | 28 | const Expr& default_expr() { |
23 | 29 | static Expr* expr = new Expr(); |
24 | 30 | return *expr; |
25 | 31 | } |
| 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 | + |
26 | 140 | } // namespace |
27 | 141 |
|
| 142 | +Expr Expr::DeepCopy() const { |
| 143 | + Expr copy; |
| 144 | + std::stack<CopyRecord> records; |
| 145 | + records.push(CopyRecord{this, ©}); |
| 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 | + |
28 | 167 | const Expr& Select::operand() const { |
29 | 168 | if (operand_ != nullptr) { |
30 | 169 | return *operand_; |
@@ -117,13 +256,6 @@ bool Comprehension::operator==(const Comprehension& other) const { |
117 | 256 | loop_step() == other.loop_step() && result() == other.result(); |
118 | 257 | } |
119 | 258 |
|
120 | | -namespace { |
121 | | -const Type& default_type() { |
122 | | - static Type* type = new Type(); |
123 | | - return *type; |
124 | | -} |
125 | | -} // namespace |
126 | | - |
127 | 259 | const Type& ListType::elem_type() const { |
128 | 260 | if (elem_type_ != nullptr) { |
129 | 261 | return *elem_type_; |
@@ -172,4 +304,21 @@ const Type& Type::type() const { |
172 | 304 | return default_type(); |
173 | 305 | } |
174 | 306 |
|
| 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 | + |
175 | 324 | } // namespace cel::ast_internal |
0 commit comments