|
26 | 26 | #include "absl/status/statusor.h" |
27 | 27 | #include "absl/strings/match.h" |
28 | 28 | #include "absl/strings/str_cat.h" |
29 | | -#include "absl/strings/str_format.h" |
30 | 29 | #include "absl/types/optional.h" |
31 | 30 | #include "common/ast.h" |
32 | 31 | #include "common/type.h" |
33 | | -#include "common/type_kind.h" |
34 | 32 | #include "common/type_spec_resolver.h" |
35 | 33 | #include "internal/status_macros.h" |
36 | 34 | #include "google/protobuf/arena.h" |
@@ -64,139 +62,178 @@ void AppendEscaped(std::string* result, std::string_view str, bool escape_dot) { |
64 | 62 | } |
65 | 63 | } |
66 | 64 |
|
67 | | -absl::Status AppendTypeParameters(std::string* result, const Type& type); |
| 65 | +absl::Status AppendTypeDesc(std::string* result, const TypeSpec& type_spec); |
68 | 66 |
|
69 | | -// Recursively appends a string representation of the given `type` to `result`. |
70 | | -// Type parameters are enclosed in angle brackets and separated by commas. |
71 | | -// |
72 | | -// Grammar: |
73 | | -// TypeDesc = NamespaceIdentifier [ "<" TypeList ">" ] ; |
74 | | -// NamespaceIdentifier = [ "." ] Identifier { "." Identifier } ; |
75 | | -// TypeList = TypeElem { "," TypeElem } ; |
76 | | -// TypeElem = TypeDesc | TypeParam |
77 | | -// TypeParam = "~" Alpha ; |
78 | | -// Identifier = ( Alpha | "_" ) { AlphaNumeric | "_" } ; |
79 | | -// (* Terminals *) |
80 | | -// Alpha = "a"..."z" | "A"..."Z" ; |
81 | | -// Digit = "0"..."9" ; |
82 | | -// AlphaNumeric = Alpha | Digit ; |
83 | | -// |
84 | | -// For compatibility, the implementation allows unexpected characters in |
85 | | -// type names and parameters and escapes them with a backslash. |
86 | | -absl::Status AppendTypeDesc(std::string* result, const Type& type) { |
87 | | - switch (type.kind()) { |
88 | | - case TypeKind::kNull: |
89 | | - absl::StrAppend(result, "null"); |
90 | | - break; |
91 | | - case TypeKind::kBool: |
92 | | - absl::StrAppend(result, "bool"); |
93 | | - break; |
94 | | - case TypeKind::kInt: |
95 | | - absl::StrAppend(result, "int"); |
96 | | - break; |
97 | | - case TypeKind::kUint: |
98 | | - absl::StrAppend(result, "uint"); |
99 | | - break; |
100 | | - case TypeKind::kDouble: |
101 | | - absl::StrAppend(result, "double"); |
102 | | - break; |
103 | | - case TypeKind::kString: |
104 | | - absl::StrAppend(result, "string"); |
105 | | - break; |
106 | | - case TypeKind::kBytes: |
107 | | - absl::StrAppend(result, "bytes"); |
108 | | - break; |
109 | | - case TypeKind::kDuration: |
110 | | - absl::StrAppend(result, "duration"); |
111 | | - break; |
112 | | - case TypeKind::kTimestamp: |
113 | | - absl::StrAppend(result, "timestamp"); |
114 | | - break; |
115 | | - case TypeKind::kAny: |
116 | | - absl::StrAppend(result, "any"); |
117 | | - break; |
118 | | - case TypeKind::kDyn: |
119 | | - absl::StrAppend(result, "dyn"); |
120 | | - break; |
121 | | - case TypeKind::kBoolWrapper: |
122 | | - absl::StrAppend(result, "bool_wrapper"); |
123 | | - break; |
124 | | - case TypeKind::kIntWrapper: |
125 | | - absl::StrAppend(result, "int_wrapper"); |
126 | | - break; |
127 | | - case TypeKind::kUintWrapper: |
128 | | - absl::StrAppend(result, "uint_wrapper"); |
129 | | - break; |
130 | | - case TypeKind::kDoubleWrapper: |
131 | | - absl::StrAppend(result, "double_wrapper"); |
132 | | - break; |
133 | | - case TypeKind::kStringWrapper: |
134 | | - absl::StrAppend(result, "string_wrapper"); |
135 | | - break; |
136 | | - case TypeKind::kBytesWrapper: |
137 | | - absl::StrAppend(result, "bytes_wrapper"); |
138 | | - break; |
139 | | - case TypeKind::kList: |
140 | | - absl::StrAppend(result, "list"); |
141 | | - CEL_RETURN_IF_ERROR(AppendTypeParameters(result, type)); |
142 | | - break; |
143 | | - case TypeKind::kMap: |
144 | | - absl::StrAppend(result, "map"); |
145 | | - CEL_RETURN_IF_ERROR(AppendTypeParameters(result, type)); |
146 | | - break; |
147 | | - case TypeKind::kFunction: |
148 | | - absl::StrAppend(result, "function"); |
149 | | - CEL_RETURN_IF_ERROR(AppendTypeParameters(result, type)); |
150 | | - break; |
151 | | - case TypeKind::kType: |
152 | | - absl::StrAppend(result, "type"); |
153 | | - CEL_RETURN_IF_ERROR(AppendTypeParameters(result, type)); |
154 | | - break; |
155 | | - case TypeKind::kTypeParam: |
156 | | - absl::StrAppend(result, "~"); |
157 | | - AppendEscaped(result, type.GetTypeParam().name(), /*escape_dot=*/true); |
158 | | - break; |
159 | | - case TypeKind::kOpaque: |
160 | | - AppendEscaped(result, type.name(), /*escape_dot=*/false); |
161 | | - CEL_RETURN_IF_ERROR(AppendTypeParameters(result, type)); |
162 | | - break; |
163 | | - case TypeKind::kStruct: |
164 | | - AppendEscaped(result, type.name(), /*escape_dot=*/false); |
165 | | - CEL_RETURN_IF_ERROR(AppendTypeParameters(result, type)); |
166 | | - break; |
167 | | - default: |
168 | | - return absl::InvalidArgumentError( |
169 | | - absl::StrFormat("Type kind: %s is not supported in CEL declarations", |
170 | | - type.DebugString())); |
| 67 | +absl::Status AppendTypeSpecList(std::string* result, |
| 68 | + const std::vector<TypeSpec>& params) { |
| 69 | + if (!params.empty()) { |
| 70 | + result->push_back('<'); |
| 71 | + for (size_t i = 0; i < params.size(); ++i) { |
| 72 | + CEL_RETURN_IF_ERROR(AppendTypeDesc(result, params[i])); |
| 73 | + if (i < params.size() - 1) { |
| 74 | + result->push_back(','); |
| 75 | + } |
| 76 | + } |
| 77 | + result->push_back('>'); |
171 | 78 | } |
172 | 79 | return absl::OkStatus(); |
173 | 80 | } |
174 | 81 |
|
175 | | -absl::Status AppendTypeParameters(std::string* result, const Type& type) { |
176 | | - const auto& parameters = type.GetParameters(); |
177 | | - if (!parameters.empty()) { |
178 | | - result->push_back('<'); |
179 | | - for (size_t i = 0; i < parameters.size(); ++i) { |
180 | | - CEL_RETURN_IF_ERROR(AppendTypeDesc(result, parameters[i])); |
181 | | - if (i < parameters.size() - 1) { |
182 | | - result->push_back(','); |
183 | | - } |
| 82 | +absl::Status AppendTypeDesc(std::string* result, const TypeSpec& type_spec) { |
| 83 | + if (type_spec.has_null()) { |
| 84 | + absl::StrAppend(result, "null"); |
| 85 | + } else if (type_spec.has_dyn()) { |
| 86 | + absl::StrAppend(result, "dyn"); |
| 87 | + } else if (type_spec.has_primitive()) { |
| 88 | + switch (type_spec.primitive()) { |
| 89 | + case PrimitiveType::kBool: |
| 90 | + absl::StrAppend(result, "bool"); |
| 91 | + break; |
| 92 | + case PrimitiveType::kInt64: |
| 93 | + absl::StrAppend(result, "int"); |
| 94 | + break; |
| 95 | + case PrimitiveType::kUint64: |
| 96 | + absl::StrAppend(result, "uint"); |
| 97 | + break; |
| 98 | + case PrimitiveType::kDouble: |
| 99 | + absl::StrAppend(result, "double"); |
| 100 | + break; |
| 101 | + case PrimitiveType::kString: |
| 102 | + absl::StrAppend(result, "string"); |
| 103 | + break; |
| 104 | + case PrimitiveType::kBytes: |
| 105 | + absl::StrAppend(result, "bytes"); |
| 106 | + break; |
| 107 | + default: |
| 108 | + return absl::InvalidArgumentError("Unsupported primitive type"); |
| 109 | + } |
| 110 | + } else if (type_spec.has_well_known()) { |
| 111 | + switch (type_spec.well_known()) { |
| 112 | + case WellKnownTypeSpec::kAny: |
| 113 | + absl::StrAppend(result, "any"); |
| 114 | + break; |
| 115 | + case WellKnownTypeSpec::kTimestamp: |
| 116 | + absl::StrAppend(result, "timestamp"); |
| 117 | + break; |
| 118 | + case WellKnownTypeSpec::kDuration: |
| 119 | + absl::StrAppend(result, "duration"); |
| 120 | + break; |
| 121 | + default: |
| 122 | + return absl::InvalidArgumentError("Unsupported well-known type"); |
184 | 123 | } |
| 124 | + } else if (type_spec.has_wrapper()) { |
| 125 | + switch (type_spec.wrapper()) { |
| 126 | + case PrimitiveType::kBool: |
| 127 | + absl::StrAppend(result, "bool_wrapper"); |
| 128 | + break; |
| 129 | + case PrimitiveType::kInt64: |
| 130 | + absl::StrAppend(result, "int_wrapper"); |
| 131 | + break; |
| 132 | + case PrimitiveType::kUint64: |
| 133 | + absl::StrAppend(result, "uint_wrapper"); |
| 134 | + break; |
| 135 | + case PrimitiveType::kDouble: |
| 136 | + absl::StrAppend(result, "double_wrapper"); |
| 137 | + break; |
| 138 | + case PrimitiveType::kString: |
| 139 | + absl::StrAppend(result, "string_wrapper"); |
| 140 | + break; |
| 141 | + case PrimitiveType::kBytes: |
| 142 | + absl::StrAppend(result, "bytes_wrapper"); |
| 143 | + break; |
| 144 | + default: |
| 145 | + return absl::InvalidArgumentError("Unsupported wrapper type"); |
| 146 | + } |
| 147 | + } else if (type_spec.has_list_type()) { |
| 148 | + absl::StrAppend(result, "list<"); |
| 149 | + if (type_spec.list_type().elem_type().is_specified()) { |
| 150 | + CEL_RETURN_IF_ERROR( |
| 151 | + AppendTypeDesc(result, type_spec.list_type().elem_type())); |
| 152 | + } else { |
| 153 | + absl::StrAppend(result, "dyn"); |
| 154 | + } |
| 155 | + result->push_back('>'); |
| 156 | + } else if (type_spec.has_map_type()) { |
| 157 | + absl::StrAppend(result, "map<"); |
| 158 | + if (type_spec.map_type().key_type().is_specified()) { |
| 159 | + CEL_RETURN_IF_ERROR( |
| 160 | + AppendTypeDesc(result, type_spec.map_type().key_type())); |
| 161 | + } else { |
| 162 | + absl::StrAppend(result, "dyn"); |
| 163 | + } |
| 164 | + result->push_back(','); |
| 165 | + if (type_spec.map_type().value_type().is_specified()) { |
| 166 | + CEL_RETURN_IF_ERROR( |
| 167 | + AppendTypeDesc(result, type_spec.map_type().value_type())); |
| 168 | + } else { |
| 169 | + absl::StrAppend(result, "dyn"); |
| 170 | + } |
| 171 | + result->push_back('>'); |
| 172 | + } else if (type_spec.has_function()) { |
| 173 | + absl::StrAppend(result, "function<"); |
| 174 | + if (type_spec.function().result_type().is_specified()) { |
| 175 | + CEL_RETURN_IF_ERROR( |
| 176 | + AppendTypeDesc(result, type_spec.function().result_type())); |
| 177 | + } else { |
| 178 | + absl::StrAppend(result, "dyn"); |
| 179 | + } |
| 180 | + for (const auto& arg : type_spec.function().arg_types()) { |
| 181 | + result->push_back(','); |
| 182 | + CEL_RETURN_IF_ERROR(AppendTypeDesc(result, arg)); |
| 183 | + } |
| 184 | + result->push_back('>'); |
| 185 | + } else if (type_spec.has_type()) { |
| 186 | + absl::StrAppend(result, "type"); |
| 187 | + result->push_back('<'); |
| 188 | + CEL_RETURN_IF_ERROR(AppendTypeDesc(result, type_spec.type())); |
185 | 189 | result->push_back('>'); |
| 190 | + } else if (type_spec.has_type_param()) { |
| 191 | + absl::StrAppend(result, "~"); |
| 192 | + AppendEscaped(result, type_spec.type_param().type(), /*escape_dot=*/true); |
| 193 | + } else if (type_spec.has_abstract_type()) { |
| 194 | + AppendEscaped(result, type_spec.abstract_type().name(), |
| 195 | + /*escape_dot=*/false); |
| 196 | + CEL_RETURN_IF_ERROR(AppendTypeSpecList( |
| 197 | + result, type_spec.abstract_type().parameter_types())); |
| 198 | + } else if (type_spec.has_message_type()) { |
| 199 | + AppendEscaped(result, type_spec.message_type().type(), |
| 200 | + /*escape_dot=*/false); |
| 201 | + } else { |
| 202 | + return absl::InvalidArgumentError(absl::StrCat( |
| 203 | + "Unsupported type in signature: ", FormatTypeSpec(type_spec))); |
186 | 204 | } |
187 | 205 | return absl::OkStatus(); |
188 | 206 | } |
189 | 207 | } // namespace |
190 | 208 |
|
191 | 209 | absl::StatusOr<std::string> MakeTypeSignature(const Type& type) { |
192 | 210 | std::string result; |
193 | | - CEL_RETURN_IF_ERROR(AppendTypeDesc(&result, type)); |
| 211 | + CEL_ASSIGN_OR_RETURN(TypeSpec type_spec, ConvertTypeToTypeSpec(type)); |
| 212 | + CEL_RETURN_IF_ERROR(AppendTypeDesc(&result, type_spec)); |
| 213 | + return result; |
| 214 | +} |
| 215 | + |
| 216 | +absl::StatusOr<std::string> MakeTypeSpecSignature(const TypeSpec& type_spec) { |
| 217 | + std::string result; |
| 218 | + CEL_RETURN_IF_ERROR(AppendTypeDesc(&result, type_spec)); |
194 | 219 | return result; |
195 | 220 | } |
196 | 221 |
|
197 | 222 | absl::StatusOr<std::string> MakeOverloadSignature( |
198 | 223 | std::string_view function_name, const std::vector<Type>& args, |
199 | 224 | bool is_member) { |
| 225 | + std::vector<TypeSpec> arg_type_specs; |
| 226 | + arg_type_specs.reserve(args.size()); |
| 227 | + for (const auto& arg : args) { |
| 228 | + CEL_ASSIGN_OR_RETURN(TypeSpec type_spec, ConvertTypeToTypeSpec(arg)); |
| 229 | + arg_type_specs.push_back(type_spec); |
| 230 | + } |
| 231 | + return MakeOverloadSignature(function_name, arg_type_specs, is_member); |
| 232 | +} |
| 233 | + |
| 234 | +absl::StatusOr<std::string> MakeOverloadSignature( |
| 235 | + std::string_view function_name, const std::vector<TypeSpec>& args, |
| 236 | + bool is_member) { |
200 | 237 | std::string result; |
201 | 238 | if (is_member) { |
202 | 239 | if (!args.empty()) { |
@@ -589,10 +626,14 @@ absl::StatusOr<ParsedFunctionOverload> ParseFunctionSignature( |
589 | 626 | return out; |
590 | 627 | } |
591 | 628 |
|
| 629 | +absl::StatusOr<TypeSpec> ParseTypeSpec(std::string_view signature) { |
| 630 | + std::string stripped_sig = StripUnescapedWhitespace(signature); |
| 631 | + return ParseTypeSignature(stripped_sig); |
| 632 | +} |
| 633 | + |
592 | 634 | absl::StatusOr<Type> ParseType(std::string_view signature, google::protobuf::Arena* arena, |
593 | 635 | const google::protobuf::DescriptorPool& pool) { |
594 | | - std::string stripped_sig = StripUnescapedWhitespace(signature); |
595 | | - CEL_ASSIGN_OR_RETURN(auto type_spec, ParseTypeSignature(stripped_sig)); |
| 636 | + CEL_ASSIGN_OR_RETURN(auto type_spec, ParseTypeSpec(signature)); |
596 | 637 | return cel::ConvertTypeSpecToType(type_spec, arena, pool); |
597 | 638 | } |
598 | 639 |
|
|
0 commit comments