Skip to content

Commit 5c9ee3e

Browse files
dmitriplotnikovcopybara-github
authored andcommitted
Refactor type signature generation to use TypeSpec.
Refactors the internal signature generation logic to operate on `cel::TypeSpec` instead of `cel::Type`. Adds a utility to convert `cel::Type` to `cel::TypeSpec` PiperOrigin-RevId: 924976939
1 parent a75e273 commit 5c9ee3e

9 files changed

Lines changed: 571 additions & 275 deletions

File tree

common/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ cc_library(
5353
deps = [
5454
":ast",
5555
":type",
56+
":type_kind",
5657
"//internal:status_macros",
5758
"@com_google_absl//absl/status",
5859
"@com_google_absl//absl/status:statusor",

common/ast/metadata.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,10 @@ class TypeSpec {
573573

574574
TypeSpecKind& mutable_type_kind() { return type_kind_; }
575575

576+
bool is_specified() const {
577+
return !absl::holds_alternative<UnsetTypeSpec>(type_kind_);
578+
}
579+
576580
bool has_dyn() const {
577581
return absl::holds_alternative<DynTypeSpec>(type_kind_);
578582
}

common/internal/BUILD

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,13 +145,11 @@ cc_library(
145145
deps = [
146146
"//common:ast",
147147
"//common:type",
148-
"//common:type_kind",
149148
"//common:type_spec_resolver",
150149
"//internal:status_macros",
151150
"@com_google_absl//absl/status",
152151
"@com_google_absl//absl/status:statusor",
153152
"@com_google_absl//absl/strings",
154-
"@com_google_absl//absl/strings:str_format",
155153
"@com_google_absl//absl/types:optional",
156154
"@com_google_protobuf//:protobuf",
157155
],
@@ -165,6 +163,7 @@ cc_test(
165163
"//common:ast",
166164
"//common:type",
167165
"//common:type_kind",
166+
"//common:type_spec_resolver",
168167
"//internal:testing",
169168
"//internal:testing_descriptor_pool",
170169
"@com_google_absl//absl/base:no_destructor",

common/internal/signature.cc

Lines changed: 158 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,9 @@
2626
#include "absl/status/statusor.h"
2727
#include "absl/strings/match.h"
2828
#include "absl/strings/str_cat.h"
29-
#include "absl/strings/str_format.h"
3029
#include "absl/types/optional.h"
3130
#include "common/ast.h"
3231
#include "common/type.h"
33-
#include "common/type_kind.h"
3432
#include "common/type_spec_resolver.h"
3533
#include "internal/status_macros.h"
3634
#include "google/protobuf/arena.h"
@@ -64,139 +62,178 @@ void AppendEscaped(std::string* result, std::string_view str, bool escape_dot) {
6462
}
6563
}
6664

67-
absl::Status AppendTypeParameters(std::string* result, const Type& type);
65+
absl::Status AppendTypeDesc(std::string* result, const TypeSpec& type_spec);
6866

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('>');
17178
}
17279
return absl::OkStatus();
17380
}
17481

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");
184123
}
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()));
185189
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)));
186204
}
187205
return absl::OkStatus();
188206
}
189207
} // namespace
190208

191209
absl::StatusOr<std::string> MakeTypeSignature(const Type& type) {
192210
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));
194219
return result;
195220
}
196221

197222
absl::StatusOr<std::string> MakeOverloadSignature(
198223
std::string_view function_name, const std::vector<Type>& args,
199224
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) {
200237
std::string result;
201238
if (is_member) {
202239
if (!args.empty()) {
@@ -589,10 +626,14 @@ absl::StatusOr<ParsedFunctionOverload> ParseFunctionSignature(
589626
return out;
590627
}
591628

629+
absl::StatusOr<TypeSpec> ParseTypeSpec(std::string_view signature) {
630+
std::string stripped_sig = StripUnescapedWhitespace(signature);
631+
return ParseTypeSignature(stripped_sig);
632+
}
633+
592634
absl::StatusOr<Type> ParseType(std::string_view signature, google::protobuf::Arena* arena,
593635
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));
596637
return cel::ConvertTypeSpecToType(type_spec, arena, pool);
597638
}
598639

0 commit comments

Comments
 (0)