/proc/self/cwd/common/ast/metadata.h
Line | Count | Source |
1 | | // Copyright 2022 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 | | // Type definitions for auxiliary structures in the AST. |
16 | | // |
17 | | // These are more direct equivalents to the public protobuf definitions. |
18 | | // |
19 | | // IWYU pragma: private, include "common/ast.h" |
20 | | #ifndef THIRD_PARTY_CEL_CPP_COMMON_AST_METADATA_H_ |
21 | | #define THIRD_PARTY_CEL_CPP_COMMON_AST_METADATA_H_ |
22 | | |
23 | | #include <cstdint> |
24 | | #include <memory> |
25 | | #include <string> |
26 | | #include <utility> |
27 | | #include <vector> |
28 | | |
29 | | #include "absl/base/nullability.h" |
30 | | #include "absl/container/flat_hash_map.h" |
31 | | #include "absl/types/optional.h" |
32 | | #include "absl/types/variant.h" |
33 | | #include "common/constant.h" |
34 | | #include "common/expr.h" |
35 | | |
36 | | namespace cel { |
37 | | |
38 | | // An extension that was requested for the source expression. |
39 | | class ExtensionSpec { |
40 | | public: |
41 | | // Version |
42 | | class Version { |
43 | | public: |
44 | 0 | Version() : major_(0), minor_(0) {} |
45 | 0 | Version(int64_t major, int64_t minor) : major_(major), minor_(minor) {} |
46 | | |
47 | | Version(const Version& other) = default; |
48 | | Version(Version&& other) = default; |
49 | | Version& operator=(const Version& other) = default; |
50 | | Version& operator=(Version&& other) = default; |
51 | | |
52 | | static const Version& DefaultInstance(); |
53 | | |
54 | | // Major version changes indicate different required support level from |
55 | | // the required components. |
56 | 0 | int64_t major() const { return major_; } |
57 | 0 | void set_major(int64_t val) { major_ = val; } |
58 | | |
59 | | // Minor version changes must not change the observed behavior from |
60 | | // existing implementations, but may be provided informationally. |
61 | 0 | int64_t minor() const { return minor_; } |
62 | 0 | void set_minor(int64_t val) { minor_ = val; } |
63 | | |
64 | 0 | bool operator==(const Version& other) const { |
65 | 0 | return major_ == other.major_ && minor_ == other.minor_; |
66 | 0 | } |
67 | | |
68 | 0 | bool operator!=(const Version& other) const { return !operator==(other); } |
69 | | |
70 | | private: |
71 | | int64_t major_; |
72 | | int64_t minor_; |
73 | | }; |
74 | | |
75 | | // CEL component specifier. |
76 | | enum class Component { |
77 | | // Unspecified, default. |
78 | | kUnspecified, |
79 | | // Parser. Converts a CEL string to an AST. |
80 | | kParser, |
81 | | // Type checker. Checks that references in an AST are defined and types |
82 | | // agree. |
83 | | kTypeChecker, |
84 | | // Runtime. Evaluates a parsed and optionally checked CEL AST against a |
85 | | // context. |
86 | | kRuntime |
87 | | }; |
88 | | |
89 | | static const ExtensionSpec& DefaultInstance(); |
90 | | |
91 | 0 | ExtensionSpec() = default; |
92 | | ExtensionSpec(std::string id, std::unique_ptr<Version> version, |
93 | | std::vector<Component> affected_components) |
94 | | : id_(std::move(id)), |
95 | | affected_components_(std::move(affected_components)), |
96 | 0 | version_(std::move(version)) {} |
97 | | |
98 | | ExtensionSpec(const ExtensionSpec& other); |
99 | | ExtensionSpec(ExtensionSpec&& other) = default; |
100 | | ExtensionSpec& operator=(const ExtensionSpec& other); |
101 | | ExtensionSpec& operator=(ExtensionSpec&& other) = default; |
102 | | |
103 | | // Identifier for the extension. Example: constant_folding |
104 | 0 | const std::string& id() const { return id_; } |
105 | 0 | void set_id(std::string id) { id_ = std::move(id); } |
106 | | |
107 | | // If set, the listed components must understand the extension for the |
108 | | // expression to evaluate correctly. |
109 | | // |
110 | | // This field has set semantics, repeated values should be deduplicated. |
111 | 0 | const std::vector<Component>& affected_components() const { |
112 | 0 | return affected_components_; |
113 | 0 | } |
114 | | |
115 | 0 | std::vector<Component>& mutable_affected_components() { |
116 | 0 | return affected_components_; |
117 | 0 | } |
118 | | |
119 | | // Version info. May be skipped if it isn't meaningful for the extension. |
120 | | // (for example constant_folding might always be v0.0). |
121 | 0 | const Version& version() const { |
122 | 0 | if (version_ == nullptr) { |
123 | 0 | return Version::DefaultInstance(); |
124 | 0 | } |
125 | 0 | return *version_; |
126 | 0 | } |
127 | | |
128 | 0 | Version& mutable_version() { |
129 | 0 | if (version_ == nullptr) { |
130 | 0 | version_ = std::make_unique<Version>(); |
131 | 0 | } |
132 | 0 | return *version_; |
133 | 0 | } |
134 | | |
135 | 0 | void set_version(std::unique_ptr<Version> version) { |
136 | 0 | version_ = std::move(version); |
137 | 0 | } |
138 | | |
139 | 0 | bool operator==(const ExtensionSpec& other) const { |
140 | 0 | return id_ == other.id_ && |
141 | 0 | affected_components_ == other.affected_components_ && |
142 | 0 | version() == other.version(); |
143 | 0 | } |
144 | | |
145 | 0 | bool operator!=(const ExtensionSpec& other) const { |
146 | 0 | return !operator==(other); |
147 | 0 | } |
148 | | |
149 | | private: |
150 | | std::string id_; |
151 | | std::vector<Component> affected_components_; |
152 | | std::unique_ptr<Version> version_; |
153 | | }; |
154 | | |
155 | | // Source information collected at parse time. |
156 | | class SourceInfo { |
157 | | public: |
158 | 1.32k | SourceInfo() = default; |
159 | | SourceInfo(std::string syntax_version, std::string location, |
160 | | std::vector<int32_t> line_offsets, |
161 | | absl::flat_hash_map<int64_t, int32_t> positions, |
162 | | absl::flat_hash_map<int64_t, Expr> macro_calls, |
163 | | std::vector<ExtensionSpec> extensions) |
164 | | : syntax_version_(std::move(syntax_version)), |
165 | | location_(std::move(location)), |
166 | | line_offsets_(std::move(line_offsets)), |
167 | | positions_(std::move(positions)), |
168 | | macro_calls_(std::move(macro_calls)), |
169 | 0 | extensions_(std::move(extensions)) {} |
170 | | |
171 | | SourceInfo(const SourceInfo& other) = default; |
172 | 2.64k | SourceInfo(SourceInfo&& other) = default; |
173 | | SourceInfo& operator=(const SourceInfo& other) = default; |
174 | | SourceInfo& operator=(SourceInfo&& other) = default; |
175 | | |
176 | 0 | void set_syntax_version(std::string syntax_version) { |
177 | 0 | syntax_version_ = std::move(syntax_version); |
178 | 0 | } |
179 | | |
180 | 1.32k | void set_location(std::string location) { location_ = std::move(location); } |
181 | | |
182 | 0 | void set_line_offsets(std::vector<int32_t> line_offsets) { |
183 | 0 | line_offsets_ = std::move(line_offsets); |
184 | 0 | } |
185 | | |
186 | 0 | void set_positions(absl::flat_hash_map<int64_t, int32_t> positions) { |
187 | 0 | positions_ = std::move(positions); |
188 | 0 | } |
189 | | |
190 | 0 | void set_macro_calls(absl::flat_hash_map<int64_t, Expr> macro_calls) { |
191 | 0 | macro_calls_ = std::move(macro_calls); |
192 | 0 | } |
193 | | |
194 | 1.32k | const std::string& syntax_version() const { return syntax_version_; } |
195 | | |
196 | 1.32k | const std::string& location() const { return location_; } |
197 | | |
198 | 1.32k | const std::vector<int32_t>& line_offsets() const { return line_offsets_; } |
199 | | |
200 | 1.28M | std::vector<int32_t>& mutable_line_offsets() { return line_offsets_; } |
201 | | |
202 | 1.71M | const absl::flat_hash_map<int64_t, int32_t>& positions() const { |
203 | 1.71M | return positions_; |
204 | 1.71M | } |
205 | | |
206 | 1.71M | absl::flat_hash_map<int64_t, int32_t>& mutable_positions() { |
207 | 1.71M | return positions_; |
208 | 1.71M | } |
209 | | |
210 | 2.64k | const absl::flat_hash_map<int64_t, Expr>& macro_calls() const { |
211 | 2.64k | return macro_calls_; |
212 | 2.64k | } |
213 | | |
214 | 1.32k | absl::flat_hash_map<int64_t, Expr>& mutable_macro_calls() { |
215 | 1.32k | return macro_calls_; |
216 | 1.32k | } |
217 | | |
218 | 0 | bool operator==(const SourceInfo& other) const { |
219 | 0 | return syntax_version_ == other.syntax_version_ && |
220 | 0 | location_ == other.location_ && |
221 | 0 | line_offsets_ == other.line_offsets_ && |
222 | 0 | positions_ == other.positions_ && |
223 | 0 | macro_calls_ == other.macro_calls_ && |
224 | 0 | extensions_ == other.extensions_; |
225 | 0 | } |
226 | | |
227 | 0 | bool operator!=(const SourceInfo& other) const { return !operator==(other); } |
228 | | |
229 | 1.32k | const std::vector<ExtensionSpec>& extensions() const { return extensions_; } |
230 | | |
231 | 0 | std::vector<ExtensionSpec>& mutable_extensions() { return extensions_; } |
232 | | |
233 | | private: |
234 | | // The syntax version of the source, e.g. `cel1`. |
235 | | std::string syntax_version_; |
236 | | |
237 | | // The location name. All position information attached to an expression is |
238 | | // relative to this location. |
239 | | // |
240 | | // The location could be a file, UI element, or similar. For example, |
241 | | // `acme/app/AnvilPolicy.cel`. |
242 | | std::string location_; |
243 | | |
244 | | // Monotonically increasing list of code point offsets where newlines |
245 | | // `\n` appear. |
246 | | // |
247 | | // The line number of a given position is the index `i` where for a given |
248 | | // `id` the `line_offsets[i] < id_positions[id] < line_offsets[i+1]`. The |
249 | | // column may be derivd from `id_positions[id] - line_offsets[i]`. |
250 | | // |
251 | | // TODO(uncreated-issue/14): clarify this documentation |
252 | | std::vector<int32_t> line_offsets_; |
253 | | |
254 | | // A map from the parse node id (e.g. `Expr.id`) to the code point offset |
255 | | // within source. |
256 | | absl::flat_hash_map<int64_t, int32_t> positions_; |
257 | | |
258 | | // A map from the parse node id where a macro replacement was made to the |
259 | | // call `Expr` that resulted in a macro expansion. |
260 | | // |
261 | | // For example, `has(value.field)` is a function call that is replaced by a |
262 | | // `test_only` field selection in the AST. Likewise, the call |
263 | | // `list.exists(e, e > 10)` translates to a comprehension expression. The key |
264 | | // in the map corresponds to the expression id of the expanded macro, and the |
265 | | // value is the call `Expr` that was replaced. |
266 | | absl::flat_hash_map<int64_t, Expr> macro_calls_; |
267 | | |
268 | | // A list of tags for extensions that were used while parsing or type checking |
269 | | // the source expression. For example, optimizations that require special |
270 | | // runtime support may be specified. |
271 | | // |
272 | | // These are used to check feature support between components in separate |
273 | | // implementations. This can be used to either skip redundant work or |
274 | | // report an error if the extension is unsupported. |
275 | | std::vector<ExtensionSpec> extensions_; |
276 | | }; |
277 | | |
278 | | // CEL primitive types. |
279 | | enum class PrimitiveType { |
280 | | // Unspecified type. |
281 | | kPrimitiveTypeUnspecified = 0, |
282 | | // Boolean type. |
283 | | kBool = 1, |
284 | | // Int64 type. |
285 | | // |
286 | | // Proto-based integer values are widened to int64. |
287 | | kInt64 = 2, |
288 | | // Uint64 type. |
289 | | // |
290 | | // Proto-based unsigned integer values are widened to uint64. |
291 | | kUint64 = 3, |
292 | | // Double type. |
293 | | // |
294 | | // Proto-based float values are widened to double values. |
295 | | kDouble = 4, |
296 | | // String type. |
297 | | kString = 5, |
298 | | // Bytes type. |
299 | | kBytes = 6, |
300 | | }; |
301 | | |
302 | | // Well-known protobuf types treated with first-class support in CEL. |
303 | | // |
304 | | // TODO(uncreated-issue/15): represent well-known via abstract types (or however) |
305 | | // they will be named. |
306 | | enum class WellKnownTypeSpec { |
307 | | // Unspecified type. |
308 | | kWellKnownTypeUnspecified = 0, |
309 | | // Well-known protobuf.Any type. |
310 | | // |
311 | | // Any types are a polymorphic message type. During type-checking they are |
312 | | // treated like `DYN` types, but at runtime they are resolved to a specific |
313 | | // message type specified at evaluation time. |
314 | | kAny = 1, |
315 | | // Well-known protobuf.Timestamp type, internally referenced as `timestamp`. |
316 | | kTimestamp = 2, |
317 | | // Well-known protobuf.Duration type, internally referenced as `duration`. |
318 | | kDuration = 3, |
319 | | }; |
320 | | |
321 | | // forward declare for recursive types. |
322 | | class TypeSpec; |
323 | | |
324 | | // List type with typed elements, e.g. `list<example.proto.MyMessage>`. |
325 | | class ListTypeSpec { |
326 | | public: |
327 | | ListTypeSpec() = default; |
328 | | |
329 | | ListTypeSpec(const ListTypeSpec& rhs); |
330 | | ListTypeSpec& operator=(const ListTypeSpec& rhs); |
331 | 0 | ListTypeSpec(ListTypeSpec&& rhs) = default; |
332 | 0 | ListTypeSpec& operator=(ListTypeSpec&& rhs) = default; |
333 | | |
334 | | explicit ListTypeSpec(std::unique_ptr<TypeSpec> elem_type); |
335 | | |
336 | | void set_elem_type(std::unique_ptr<TypeSpec> elem_type); |
337 | | |
338 | 0 | bool has_elem_type() const { return elem_type_ != nullptr; } |
339 | | |
340 | | const TypeSpec& elem_type() const; |
341 | | |
342 | | TypeSpec& mutable_elem_type(); |
343 | | |
344 | | bool operator==(const ListTypeSpec& other) const; |
345 | | |
346 | | private: |
347 | | std::unique_ptr<TypeSpec> elem_type_; |
348 | | }; |
349 | | |
350 | | // Map type specifier with parameterized key and value types, e.g. |
351 | | // `map<string, int>`. |
352 | | class MapTypeSpec { |
353 | | public: |
354 | | MapTypeSpec() = default; |
355 | | MapTypeSpec(std::unique_ptr<TypeSpec> key_type, |
356 | | std::unique_ptr<TypeSpec> value_type); |
357 | | |
358 | | MapTypeSpec(const MapTypeSpec& rhs); |
359 | | MapTypeSpec& operator=(const MapTypeSpec& rhs); |
360 | 0 | MapTypeSpec(MapTypeSpec&& rhs) = default; |
361 | 0 | MapTypeSpec& operator=(MapTypeSpec&& rhs) = default; |
362 | | |
363 | | void set_key_type(std::unique_ptr<TypeSpec> key_type); |
364 | | |
365 | | void set_value_type(std::unique_ptr<TypeSpec> value_type); |
366 | | |
367 | 0 | bool has_key_type() const { return key_type_ != nullptr; } |
368 | | |
369 | 0 | bool has_value_type() const { return value_type_ != nullptr; } |
370 | | |
371 | | const TypeSpec& key_type() const; |
372 | | |
373 | | const TypeSpec& value_type() const; |
374 | | |
375 | | bool operator==(const MapTypeSpec& other) const; |
376 | | |
377 | | TypeSpec& mutable_key_type(); |
378 | | |
379 | | TypeSpec& mutable_value_type(); |
380 | | |
381 | | private: |
382 | | // The type of the key. |
383 | | std::unique_ptr<TypeSpec> key_type_; |
384 | | |
385 | | // The type of the value. |
386 | | std::unique_ptr<TypeSpec> value_type_; |
387 | | }; |
388 | | |
389 | | // Function type specifiers with result and arg types. |
390 | | // |
391 | | // NOTE: function type represents a lambda-style argument to another function. |
392 | | // Supported through macros, but not yet a first-class concept in CEL. |
393 | | class FunctionTypeSpec { |
394 | | public: |
395 | | FunctionTypeSpec() = default; |
396 | | FunctionTypeSpec(std::unique_ptr<TypeSpec> result_type, |
397 | | std::vector<TypeSpec> arg_types); |
398 | | |
399 | | FunctionTypeSpec(const FunctionTypeSpec& other); |
400 | | FunctionTypeSpec& operator=(const FunctionTypeSpec& other); |
401 | 0 | FunctionTypeSpec(FunctionTypeSpec&&) = default; |
402 | 0 | FunctionTypeSpec& operator=(FunctionTypeSpec&&) = default; |
403 | | |
404 | | void set_result_type(std::unique_ptr<TypeSpec> result_type); |
405 | | |
406 | | void set_arg_types(std::vector<TypeSpec> arg_types); |
407 | | |
408 | 0 | bool has_result_type() const { return result_type_ != nullptr; } |
409 | | |
410 | | const TypeSpec& result_type() const; |
411 | | |
412 | | TypeSpec& mutable_result_type(); |
413 | | |
414 | 0 | const std::vector<TypeSpec>& arg_types() const { return arg_types_; } |
415 | | |
416 | 0 | std::vector<TypeSpec>& mutable_arg_types() { return arg_types_; } |
417 | | |
418 | | bool operator==(const FunctionTypeSpec& other) const; |
419 | | |
420 | | private: |
421 | | // Result type of the function. |
422 | | std::unique_ptr<TypeSpec> result_type_; |
423 | | |
424 | | // Argument types of the function. |
425 | | std::vector<TypeSpec> arg_types_; |
426 | | }; |
427 | | |
428 | | // Application defined abstract type. |
429 | | // |
430 | | // Abstract types provide a name as an identifier for the application, and |
431 | | // optionally one or more type parameters. |
432 | | // |
433 | | // For cel::Type representation, see OpaqueType. |
434 | | class AbstractType { |
435 | | public: |
436 | | AbstractType() = default; |
437 | | AbstractType(std::string name, std::vector<TypeSpec> parameter_types); |
438 | | |
439 | 0 | void set_name(std::string name) { name_ = std::move(name); } |
440 | | |
441 | | void set_parameter_types(std::vector<TypeSpec> parameter_types); |
442 | | |
443 | 0 | const std::string& name() const { return name_; } |
444 | | |
445 | 0 | const std::vector<TypeSpec>& parameter_types() const { |
446 | 0 | return parameter_types_; |
447 | 0 | } |
448 | | |
449 | 0 | std::vector<TypeSpec>& mutable_parameter_types() { return parameter_types_; } |
450 | | |
451 | | bool operator==(const AbstractType& other) const; |
452 | | |
453 | | private: |
454 | | // The fully qualified name of this abstract type. |
455 | | std::string name_; |
456 | | |
457 | | // Parameter types for this abstract type. |
458 | | std::vector<TypeSpec> parameter_types_; |
459 | | }; |
460 | | |
461 | | // Wrapper of a primitive type, e.g. `google.protobuf.Int64Value`. |
462 | | class PrimitiveTypeWrapper { |
463 | | public: |
464 | 0 | explicit PrimitiveTypeWrapper(PrimitiveType type) : type_(std::move(type)) {} |
465 | | |
466 | 0 | void set_type(PrimitiveType type) { type_ = std::move(type); } |
467 | | |
468 | 0 | const PrimitiveType& type() const { return type_; } |
469 | | |
470 | 0 | PrimitiveType& mutable_type() { return type_; } |
471 | | |
472 | 0 | bool operator==(const PrimitiveTypeWrapper& other) const { |
473 | 0 | return type_ == other.type_; |
474 | 0 | } |
475 | | |
476 | | private: |
477 | | PrimitiveType type_; |
478 | | }; |
479 | | |
480 | | // Protocol buffer message type specifier. |
481 | | // |
482 | | // The `message_type` string specifies the qualified message type name. For |
483 | | // example, `google.plus.Profile`. This must be mapped to a google::protobuf::Descriptor |
484 | | // for type checking. |
485 | | class MessageTypeSpec { |
486 | | public: |
487 | | MessageTypeSpec() = default; |
488 | 0 | explicit MessageTypeSpec(std::string type) : type_(std::move(type)) {} |
489 | | |
490 | 0 | void set_type(std::string type) { type_ = std::move(type); } |
491 | | |
492 | 0 | const std::string& type() const { return type_; } |
493 | | |
494 | 0 | bool operator==(const MessageTypeSpec& other) const { |
495 | 0 | return type_ == other.type_; |
496 | 0 | } |
497 | | |
498 | | private: |
499 | | std::string type_; |
500 | | }; |
501 | | |
502 | | // TypeSpec param type. |
503 | | // |
504 | | // The `type_param` string specifies the type parameter name, e.g. `list<E>` |
505 | | // would be a `list_type` whose element type was a `type_param` type |
506 | | // named `E`. |
507 | | class ParamTypeSpec { |
508 | | public: |
509 | | ParamTypeSpec() = default; |
510 | 0 | explicit ParamTypeSpec(std::string type) : type_(std::move(type)) {} |
511 | | |
512 | 0 | void set_type(std::string type) { type_ = std::move(type); } |
513 | | |
514 | 0 | const std::string& type() const { return type_; } |
515 | | |
516 | 0 | bool operator==(const ParamTypeSpec& other) const { |
517 | 0 | return type_ == other.type_; |
518 | 0 | } |
519 | | |
520 | | private: |
521 | | std::string type_; |
522 | | }; |
523 | | |
524 | | // Error type specifier. |
525 | | // |
526 | | // During type-checking if an expression is an error, its type is propagated |
527 | | // as the `ERROR` type. This permits the type-checker to discover other |
528 | | // errors present in the expression. |
529 | | enum class ErrorTypeSpec { kValue = 0 }; |
530 | | |
531 | | using UnsetTypeSpec = absl::monostate; |
532 | | |
533 | | struct DynTypeSpec {}; |
534 | | |
535 | 0 | inline bool operator==(const DynTypeSpec&, const DynTypeSpec&) { return true; } |
536 | 0 | inline bool operator!=(const DynTypeSpec&, const DynTypeSpec&) { return false; } |
537 | | |
538 | | struct NullTypeSpec {}; |
539 | 0 | inline bool operator==(const NullTypeSpec&, const NullTypeSpec&) { |
540 | 0 | return true; |
541 | 0 | } |
542 | 0 | inline bool operator!=(const NullTypeSpec&, const NullTypeSpec&) { |
543 | 0 | return false; |
544 | 0 | } |
545 | | |
546 | | using TypeSpecKind = |
547 | | absl::variant<UnsetTypeSpec, DynTypeSpec, NullTypeSpec, PrimitiveType, |
548 | | PrimitiveTypeWrapper, WellKnownTypeSpec, ListTypeSpec, |
549 | | MapTypeSpec, FunctionTypeSpec, MessageTypeSpec, ParamTypeSpec, |
550 | | absl_nullable std::unique_ptr<TypeSpec>, ErrorTypeSpec, |
551 | | AbstractType>; |
552 | | |
553 | | // Analogous to cel::expr::Type. |
554 | | // Represents a CEL type. |
555 | | // |
556 | | // TODO(uncreated-issue/15): align with value.proto |
557 | | class TypeSpec { |
558 | | public: |
559 | 0 | TypeSpec() = default; |
560 | | explicit TypeSpec(TypeSpecKind type_kind) |
561 | 0 | : type_kind_(std::move(type_kind)) {} |
562 | | |
563 | | TypeSpec(const TypeSpec& other); |
564 | | TypeSpec& operator=(const TypeSpec& other); |
565 | | TypeSpec(TypeSpec&&) = default; |
566 | | TypeSpec& operator=(TypeSpec&&) = default; |
567 | | |
568 | 0 | void set_type_kind(TypeSpecKind type_kind) { |
569 | 0 | type_kind_ = std::move(type_kind); |
570 | 0 | } |
571 | | |
572 | 0 | const TypeSpecKind& type_kind() const { return type_kind_; } |
573 | | |
574 | 0 | TypeSpecKind& mutable_type_kind() { return type_kind_; } |
575 | | |
576 | 0 | bool has_dyn() const { |
577 | 0 | return absl::holds_alternative<DynTypeSpec>(type_kind_); |
578 | 0 | } |
579 | | |
580 | 0 | bool has_null() const { |
581 | 0 | return absl::holds_alternative<NullTypeSpec>(type_kind_); |
582 | 0 | } |
583 | | |
584 | 0 | bool has_primitive() const { |
585 | 0 | return absl::holds_alternative<PrimitiveType>(type_kind_); |
586 | 0 | } |
587 | | |
588 | 0 | bool has_wrapper() const { |
589 | 0 | return absl::holds_alternative<PrimitiveTypeWrapper>(type_kind_); |
590 | 0 | } |
591 | | |
592 | 0 | bool has_well_known() const { |
593 | 0 | return absl::holds_alternative<WellKnownTypeSpec>(type_kind_); |
594 | 0 | } |
595 | | |
596 | 0 | bool has_list_type() const { |
597 | 0 | return absl::holds_alternative<ListTypeSpec>(type_kind_); |
598 | 0 | } |
599 | | |
600 | 0 | bool has_map_type() const { |
601 | 0 | return absl::holds_alternative<MapTypeSpec>(type_kind_); |
602 | 0 | } |
603 | | |
604 | 0 | bool has_function() const { |
605 | 0 | return absl::holds_alternative<FunctionTypeSpec>(type_kind_); |
606 | 0 | } |
607 | | |
608 | 0 | bool has_message_type() const { |
609 | 0 | return absl::holds_alternative<MessageTypeSpec>(type_kind_); |
610 | 0 | } |
611 | | |
612 | 0 | bool has_type_param() const { |
613 | 0 | return absl::holds_alternative<ParamTypeSpec>(type_kind_); |
614 | 0 | } |
615 | | |
616 | 0 | bool has_type() const { |
617 | 0 | return absl::holds_alternative<std::unique_ptr<TypeSpec>>(type_kind_); |
618 | 0 | } |
619 | | |
620 | 0 | bool has_error() const { |
621 | 0 | return absl::holds_alternative<ErrorTypeSpec>(type_kind_); |
622 | 0 | } |
623 | | |
624 | 0 | bool has_abstract_type() const { |
625 | 0 | return absl::holds_alternative<AbstractType>(type_kind_); |
626 | 0 | } |
627 | | |
628 | 0 | NullTypeSpec null() const { |
629 | 0 | auto* value = absl::get_if<NullTypeSpec>(&type_kind_); |
630 | 0 | if (value != nullptr) { |
631 | 0 | return *value; |
632 | 0 | } |
633 | 0 | return {}; |
634 | 0 | } |
635 | | |
636 | 0 | PrimitiveType primitive() const { |
637 | 0 | auto* value = absl::get_if<PrimitiveType>(&type_kind_); |
638 | 0 | if (value != nullptr) { |
639 | 0 | return *value; |
640 | 0 | } |
641 | 0 | return PrimitiveType::kPrimitiveTypeUnspecified; |
642 | 0 | } |
643 | | |
644 | 0 | PrimitiveType wrapper() const { |
645 | 0 | auto* value = absl::get_if<PrimitiveTypeWrapper>(&type_kind_); |
646 | 0 | if (value != nullptr) { |
647 | 0 | return value->type(); |
648 | 0 | } |
649 | 0 | return PrimitiveType::kPrimitiveTypeUnspecified; |
650 | 0 | } |
651 | | |
652 | 0 | WellKnownTypeSpec well_known() const { |
653 | 0 | auto* value = absl::get_if<WellKnownTypeSpec>(&type_kind_); |
654 | 0 | if (value != nullptr) { |
655 | 0 | return *value; |
656 | 0 | } |
657 | 0 | return WellKnownTypeSpec::kWellKnownTypeUnspecified; |
658 | 0 | } |
659 | | |
660 | 0 | const ListTypeSpec& list_type() const { |
661 | 0 | auto* value = absl::get_if<ListTypeSpec>(&type_kind_); |
662 | 0 | if (value != nullptr) { |
663 | 0 | return *value; |
664 | 0 | } |
665 | 0 | static const ListTypeSpec* default_list_type = new ListTypeSpec(); |
666 | 0 | return *default_list_type; |
667 | 0 | } |
668 | | |
669 | 0 | const MapTypeSpec& map_type() const { |
670 | 0 | auto* value = absl::get_if<MapTypeSpec>(&type_kind_); |
671 | 0 | if (value != nullptr) { |
672 | 0 | return *value; |
673 | 0 | } |
674 | 0 | static const MapTypeSpec* default_map_type = new MapTypeSpec(); |
675 | 0 | return *default_map_type; |
676 | 0 | } |
677 | | |
678 | 0 | const FunctionTypeSpec& function() const { |
679 | 0 | auto* value = absl::get_if<FunctionTypeSpec>(&type_kind_); |
680 | 0 | if (value != nullptr) { |
681 | 0 | return *value; |
682 | 0 | } |
683 | 0 | static const FunctionTypeSpec* default_function_type = |
684 | 0 | new FunctionTypeSpec(); |
685 | 0 | return *default_function_type; |
686 | 0 | } |
687 | | |
688 | 0 | const MessageTypeSpec& message_type() const { |
689 | 0 | auto* value = absl::get_if<MessageTypeSpec>(&type_kind_); |
690 | 0 | if (value != nullptr) { |
691 | 0 | return *value; |
692 | 0 | } |
693 | 0 | static const MessageTypeSpec* default_message_type = new MessageTypeSpec(); |
694 | 0 | return *default_message_type; |
695 | 0 | } |
696 | | |
697 | 0 | const ParamTypeSpec& type_param() const { |
698 | 0 | auto* value = absl::get_if<ParamTypeSpec>(&type_kind_); |
699 | 0 | if (value != nullptr) { |
700 | 0 | return *value; |
701 | 0 | } |
702 | 0 | static const ParamTypeSpec* default_param_type = new ParamTypeSpec(); |
703 | 0 | return *default_param_type; |
704 | 0 | } |
705 | | |
706 | | const TypeSpec& type() const; |
707 | | |
708 | 0 | ErrorTypeSpec error_type() const { |
709 | 0 | auto* value = absl::get_if<ErrorTypeSpec>(&type_kind_); |
710 | 0 | if (value != nullptr) { |
711 | 0 | return *value; |
712 | 0 | } |
713 | 0 | return ErrorTypeSpec::kValue; |
714 | 0 | } |
715 | | |
716 | 0 | const AbstractType& abstract_type() const { |
717 | 0 | auto* value = absl::get_if<AbstractType>(&type_kind_); |
718 | 0 | if (value != nullptr) { |
719 | 0 | return *value; |
720 | 0 | } |
721 | 0 | static const AbstractType* default_abstract_type = new AbstractType(); |
722 | 0 | return *default_abstract_type; |
723 | 0 | } |
724 | | |
725 | 0 | bool operator==(const TypeSpec& other) const { |
726 | 0 | if (absl::holds_alternative<std::unique_ptr<TypeSpec>>(type_kind_) && |
727 | 0 | absl::holds_alternative<std::unique_ptr<TypeSpec>>(other.type_kind_)) { |
728 | 0 | const auto& self_type = absl::get<std::unique_ptr<TypeSpec>>(type_kind_); |
729 | 0 | const auto& other_type = |
730 | 0 | absl::get<std::unique_ptr<TypeSpec>>(other.type_kind_); |
731 | 0 | if (self_type == nullptr || other_type == nullptr) { |
732 | 0 | return self_type == other_type; |
733 | 0 | } |
734 | 0 | return *self_type == *other_type; |
735 | 0 | } |
736 | 0 | return type_kind_ == other.type_kind_; |
737 | 0 | } |
738 | | |
739 | | private: |
740 | | TypeSpecKind type_kind_; |
741 | | }; |
742 | | |
743 | | // Describes a resolved reference to a declaration. |
744 | | class Reference { |
745 | | public: |
746 | | Reference() = default; |
747 | | |
748 | | Reference(std::string name, std::vector<std::string> overload_id, |
749 | | Constant value) |
750 | | : name_(std::move(name)), |
751 | | overload_id_(std::move(overload_id)), |
752 | 0 | value_(std::move(value)) {} |
753 | | |
754 | | Reference(const Reference& other) = default; |
755 | | Reference& operator=(const Reference& other) = default; |
756 | | Reference(Reference&&) = default; |
757 | | Reference& operator=(Reference&&) = default; |
758 | | |
759 | 0 | void set_name(std::string name) { name_ = std::move(name); } |
760 | | |
761 | 0 | void set_overload_id(std::vector<std::string> overload_id) { |
762 | 0 | overload_id_ = std::move(overload_id); |
763 | 0 | } |
764 | | |
765 | 0 | void set_value(Constant value) { value_ = std::move(value); } |
766 | | |
767 | 0 | const std::string& name() const { return name_; } |
768 | | |
769 | 0 | const std::vector<std::string>& overload_id() const { return overload_id_; } |
770 | | |
771 | 0 | const Constant& value() const { |
772 | 0 | if (value_.has_value()) { |
773 | 0 | return value_.value(); |
774 | 0 | } |
775 | 0 | static const Constant* default_constant = new Constant; |
776 | 0 | return *default_constant; |
777 | 0 | } |
778 | | |
779 | 0 | std::vector<std::string>& mutable_overload_id() { return overload_id_; } |
780 | | |
781 | 0 | Constant& mutable_value() { |
782 | 0 | if (!value_.has_value()) { |
783 | 0 | value_.emplace(); |
784 | 0 | } |
785 | 0 | return *value_; |
786 | 0 | } |
787 | | |
788 | 0 | bool has_value() const { return value_.has_value(); } |
789 | | |
790 | 0 | bool operator==(const Reference& other) const { |
791 | 0 | return name_ == other.name_ && overload_id_ == other.overload_id_ && |
792 | 0 | value() == other.value(); |
793 | 0 | } |
794 | | |
795 | | private: |
796 | | // The fully qualified name of the declaration. |
797 | | std::string name_; |
798 | | // For references to functions, this is a list of `Overload.overload_id` |
799 | | // values which match according to typing rules. |
800 | | // |
801 | | // If the list has more than one element, overload resolution among the |
802 | | // presented candidates must happen at runtime because of dynamic types. The |
803 | | // type checker attempts to narrow down this list as much as possible. |
804 | | // |
805 | | // Empty if this is not a reference to a [Decl.FunctionDecl][]. |
806 | | std::vector<std::string> overload_id_; |
807 | | // For references to constants, this may contain the value of the |
808 | | // constant if known at compile time. |
809 | | absl::optional<Constant> value_; |
810 | | }; |
811 | | |
812 | | //////////////////////////////////////////////////////////////////////// |
813 | | // Out-of-line method declarations |
814 | | //////////////////////////////////////////////////////////////////////// |
815 | | |
816 | | inline ListTypeSpec::ListTypeSpec(const ListTypeSpec& rhs) |
817 | 0 | : elem_type_(std::make_unique<TypeSpec>(rhs.elem_type())) {} |
818 | | |
819 | 0 | inline ListTypeSpec& ListTypeSpec::operator=(const ListTypeSpec& rhs) { |
820 | 0 | elem_type_ = std::make_unique<TypeSpec>(rhs.elem_type()); |
821 | 0 | return *this; |
822 | 0 | } |
823 | | |
824 | | inline ListTypeSpec::ListTypeSpec(std::unique_ptr<TypeSpec> elem_type) |
825 | | : elem_type_(std::move(elem_type)) {} |
826 | | |
827 | 0 | inline void ListTypeSpec::set_elem_type(std::unique_ptr<TypeSpec> elem_type) { |
828 | 0 | elem_type_ = std::move(elem_type); |
829 | 0 | } |
830 | | |
831 | 0 | inline TypeSpec& ListTypeSpec::mutable_elem_type() { |
832 | 0 | if (elem_type_ == nullptr) { |
833 | 0 | elem_type_ = std::make_unique<TypeSpec>(); |
834 | 0 | } |
835 | 0 | return *elem_type_; |
836 | 0 | } |
837 | | |
838 | | inline MapTypeSpec::MapTypeSpec(std::unique_ptr<TypeSpec> key_type, |
839 | | std::unique_ptr<TypeSpec> value_type) |
840 | | : key_type_(std::move(key_type)), value_type_(std::move(value_type)) {} |
841 | | |
842 | | inline MapTypeSpec::MapTypeSpec(const MapTypeSpec& rhs) |
843 | 0 | : key_type_(std::make_unique<TypeSpec>(rhs.key_type())), |
844 | 0 | value_type_(std::make_unique<TypeSpec>(rhs.value_type())) {} |
845 | | |
846 | 0 | inline MapTypeSpec& MapTypeSpec::operator=(const MapTypeSpec& rhs) { |
847 | 0 | key_type_ = std::make_unique<TypeSpec>(rhs.key_type()); |
848 | 0 | value_type_ = std::make_unique<TypeSpec>(rhs.value_type()); |
849 | 0 | return *this; |
850 | 0 | } |
851 | | |
852 | 0 | inline void MapTypeSpec::set_key_type(std::unique_ptr<TypeSpec> key_type) { |
853 | 0 | key_type_ = std::move(key_type); |
854 | 0 | } |
855 | | |
856 | 0 | inline void MapTypeSpec::set_value_type(std::unique_ptr<TypeSpec> value_type) { |
857 | 0 | value_type_ = std::move(value_type); |
858 | 0 | } |
859 | | |
860 | 0 | inline TypeSpec& MapTypeSpec::mutable_key_type() { |
861 | 0 | if (key_type_ == nullptr) { |
862 | 0 | key_type_ = std::make_unique<TypeSpec>(); |
863 | 0 | } |
864 | 0 | return *key_type_; |
865 | 0 | } |
866 | | |
867 | 0 | inline TypeSpec& MapTypeSpec::mutable_value_type() { |
868 | 0 | if (value_type_ == nullptr) { |
869 | 0 | value_type_ = std::make_unique<TypeSpec>(); |
870 | 0 | } |
871 | 0 | return *value_type_; |
872 | 0 | } |
873 | | |
874 | | inline void FunctionTypeSpec::set_result_type( |
875 | 0 | std::unique_ptr<TypeSpec> result_type) { |
876 | 0 | result_type_ = std::move(result_type); |
877 | 0 | } |
878 | | |
879 | 0 | inline TypeSpec& FunctionTypeSpec::mutable_result_type() { |
880 | 0 | if (result_type_ == nullptr) { |
881 | 0 | result_type_ = std::make_unique<TypeSpec>(); |
882 | 0 | } |
883 | 0 | return *result_type_; |
884 | 0 | } |
885 | | |
886 | | //////////////////////////////////////////////////////////////////////// |
887 | | // Implementation details |
888 | | //////////////////////////////////////////////////////////////////////// |
889 | | |
890 | | inline FunctionTypeSpec::FunctionTypeSpec(std::unique_ptr<TypeSpec> result_type, |
891 | | std::vector<TypeSpec> arg_types) |
892 | | : result_type_(std::move(result_type)), arg_types_(std::move(arg_types)) {} |
893 | | |
894 | 0 | inline void FunctionTypeSpec::set_arg_types(std::vector<TypeSpec> arg_types) { |
895 | 0 | arg_types_ = std::move(arg_types); |
896 | 0 | } |
897 | | |
898 | | inline AbstractType::AbstractType(std::string name, |
899 | | std::vector<TypeSpec> parameter_types) |
900 | | : name_(std::move(name)), parameter_types_(std::move(parameter_types)) {} |
901 | | |
902 | | inline void AbstractType::set_parameter_types( |
903 | 0 | std::vector<TypeSpec> parameter_types) { |
904 | 0 | parameter_types_ = std::move(parameter_types); |
905 | 0 | } |
906 | | |
907 | 0 | inline bool AbstractType::operator==(const AbstractType& other) const { |
908 | 0 | return name_ == other.name_ && parameter_types_ == other.parameter_types_; |
909 | 0 | } |
910 | | |
911 | | } // namespace cel |
912 | | |
913 | | #endif // THIRD_PARTY_CEL_CPP_COMMON_AST_METADATA_H_ |