Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 28 additions & 11 deletions env/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,28 @@ package(default_visibility = ["//visibility:public"])

cc_library(
name = "config",
srcs = ["config.cc"],
hdrs = ["config.h"],
srcs = [
"config.cc",
"type_info.cc",
],
hdrs = [
"config.h",
"type_info.h",
],
deps = [
"//common:constant",
"//common:type",
"//common:type_kind",
"//internal:status_macros",
"@com_google_absl//absl/base:no_destructor",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/container:flat_hash_set",
"@com_google_absl//absl/functional:overload",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/time",
"@com_google_absl//absl/types:variant",
"@com_google_protobuf//:protobuf",
],
)

Expand All @@ -43,23 +54,16 @@ cc_library(
"//common:constant",
"//common:decl",
"//common:type",
"//common:type_kind",
"//compiler",
"//compiler:compiler_factory",
"//compiler:standard_library",
"//env/internal:ext_registry",
"//internal:status_macros",
"//parser:macro",
"@com_google_absl//absl/base:no_destructor",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/container:flat_hash_set",
"@com_google_absl//absl/functional:any_invocable",
"@com_google_absl//absl/functional:overload",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/time",
"@com_google_absl//absl/types:variant",
"@com_google_protobuf//:protobuf",
],
)
Expand Down Expand Up @@ -163,6 +167,20 @@ cc_test(
],
)

cc_test(
name = "type_info_test",
srcs = ["type_info_test.cc"],
deps = [
":config",
"//common:type",
"//common:type_proto",
"//internal:proto_matchers",
"//internal:testing",
"//internal:testing_descriptor_pool",
"@com_google_protobuf//:protobuf",
],
)

cc_test(
name = "env_test",
srcs = ["env_test.cc"],
Expand All @@ -173,7 +191,6 @@ cc_test(
"//checker:type_checker_builder",
"//checker:validation_result",
"//common:ast",
"//common:ast_proto",
"//common:constant",
"//common:decl",
"//common:expr",
Expand Down
168 changes: 16 additions & 152 deletions env/env.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,22 @@
#include "env/env.h"

#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#include "absl/base/no_destructor.h"
#include "absl/container/flat_hash_map.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "checker/type_checker_builder.h"
#include "common/constant.h"
#include "common/decl.h"
#include "common/type.h"
#include "common/type_kind.h"
#include "compiler/compiler.h"
#include "compiler/compiler_factory.h"
#include "compiler/standard_library.h"
#include "env/config.h"
#include "env/type_info.h"
#include "internal/status_macros.h"
#include "parser/macro.h"
#include "google/protobuf/arena.h"
Expand Down Expand Up @@ -95,149 +93,6 @@ absl::StatusOr<CompilerLibrarySubset> MakeStdlibSubset(
return subset;
}

std::optional<TypeKind> TypeNameToTypeKind(absl::string_view type_name) {
// Excluded types:
// kUnknown
// kError
// kTypeParam
// kFunction
// kEnum

static const absl::NoDestructor<
absl::flat_hash_map<absl::string_view, TypeKind>>
kTypeNameToTypeKind({
{"null", TypeKind::kNull},
{"bool", TypeKind::kBool},
{"int", TypeKind::kInt},
{"uint", TypeKind::kUint},
{"double", TypeKind::kDouble},
{"string", TypeKind::kString},
{"bytes", TypeKind::kBytes},
{"timestamp", TypeKind::kTimestamp},
{TimestampType::kName, TypeKind::kTimestamp},
{"duration", TypeKind::kDuration},
{DurationType::kName, TypeKind::kDuration},
{"list", TypeKind::kList},
{"map", TypeKind::kMap},
{"", TypeKind::kDyn},
{"any", TypeKind::kAny},
{"dyn", TypeKind::kDyn},
{BoolWrapperType::kName, TypeKind::kBoolWrapper},
{IntWrapperType::kName, TypeKind::kIntWrapper},
{UintWrapperType::kName, TypeKind::kUintWrapper},
{DoubleWrapperType::kName, TypeKind::kDoubleWrapper},
{StringWrapperType::kName, TypeKind::kStringWrapper},
{BytesWrapperType::kName, TypeKind::kBytesWrapper},
{"type", TypeKind::kType},
});
if (auto it = kTypeNameToTypeKind->find(type_name);
it != kTypeNameToTypeKind->end()) {
return it->second;
}

return std::nullopt;
}

absl::StatusOr<Type> TypeInfoToType(
const Config::TypeInfo& type_info, google::protobuf::Arena* arena,
const google::protobuf::DescriptorPool* descriptor_pool) {
if (type_info.is_type_param) {
return TypeParamType(type_info.name);
}

std::optional<TypeKind> type_kind = TypeNameToTypeKind(type_info.name);
if (!type_kind.has_value()) {
if (type_info.params.empty() && descriptor_pool != nullptr) {
const google::protobuf::Descriptor* type =
descriptor_pool->FindMessageTypeByName(type_info.name);
if (type != nullptr) {
return MessageType(type);
}
}
// TODO(uncreated-issue/88): use a TypeIntrospector to validate opaque types
std::vector<Type> parameter_types;
for (const Config::TypeInfo& param : type_info.params) {
CEL_ASSIGN_OR_RETURN(Type parameter_type,
TypeInfoToType(param, arena, descriptor_pool));
parameter_types.push_back(parameter_type);
}

return OpaqueType(arena, type_info.name, parameter_types);
}

switch (*type_kind) {
case TypeKind::kNull:
return NullType();
case TypeKind::kBool:
return BoolType();
case TypeKind::kInt:
return IntType();
case TypeKind::kUint:
return UintType();
case TypeKind::kDouble:
return DoubleType();
case TypeKind::kString:
return StringType();
case TypeKind::kBytes:
return BytesType();
case TypeKind::kDuration:
return DurationType();
case TypeKind::kTimestamp:
return TimestampType();
case TypeKind::kList: {
Type element_type;
if (!type_info.params.empty()) {
CEL_ASSIGN_OR_RETURN(
element_type,
TypeInfoToType(type_info.params[0], arena, descriptor_pool));
} else {
element_type = DynType();
}
return ListType(arena, element_type);
}
case TypeKind::kMap: {
Type key_type = DynType();
Type value_type = DynType();
if (!type_info.params.empty()) {
CEL_ASSIGN_OR_RETURN(key_type, TypeInfoToType(type_info.params[0],
arena, descriptor_pool));
}
if (type_info.params.size() > 1) {
CEL_ASSIGN_OR_RETURN(
value_type,
TypeInfoToType(type_info.params[1], arena, descriptor_pool));
}
return MapType(arena, key_type, value_type);
}
case TypeKind::kDyn:
return DynType();
case TypeKind::kAny:
return AnyType();
case TypeKind::kBoolWrapper:
return BoolWrapperType();
case TypeKind::kIntWrapper:
return IntWrapperType();
case TypeKind::kUintWrapper:
return UintWrapperType();
case TypeKind::kDoubleWrapper:
return DoubleWrapperType();
case TypeKind::kStringWrapper:
return StringWrapperType();
case TypeKind::kBytesWrapper:
return BytesWrapperType();
case TypeKind::kType: {
if (type_info.params.empty()) {
return TypeType(arena, DynType());
}
CEL_ASSIGN_OR_RETURN(Type type, TypeInfoToType(type_info.params[0], arena,
descriptor_pool));
return TypeType(arena, type);
}
default:
return DynType();
}
}

absl::StatusOr<FunctionDecl> FunctionConfigToFunctionDecl(
const Config::FunctionConfig& function_config, google::protobuf::Arena* arena,
const google::protobuf::DescriptorPool* descriptor_pool) {
Expand All @@ -250,12 +105,12 @@ absl::StatusOr<FunctionDecl> FunctionConfigToFunctionDecl(
overload_decl.set_member(overload_config.is_member_function);
for (const Config::TypeInfo& parameter : overload_config.parameters) {
CEL_ASSIGN_OR_RETURN(Type parameter_type,
TypeInfoToType(parameter, arena, descriptor_pool));
TypeInfoToType(parameter, descriptor_pool, arena));
overload_decl.mutable_args().push_back(parameter_type);
}
CEL_ASSIGN_OR_RETURN(
Type return_type,
TypeInfoToType(overload_config.return_type, arena, descriptor_pool));
TypeInfoToType(overload_config.return_type, descriptor_pool, arena));
overload_decl.set_result(return_type);
CEL_RETURN_IF_ERROR(function_decl.AddOverload(overload_decl));
}
Expand All @@ -264,7 +119,11 @@ absl::StatusOr<FunctionDecl> FunctionConfigToFunctionDecl(

} // namespace

absl::StatusOr<std::unique_ptr<Compiler>> Env::NewCompiler() {
Env::Env() {
compiler_options_.parser_options.enable_quoted_identifiers = true;
}

absl::StatusOr<std::unique_ptr<CompilerBuilder>> Env::NewCompilerBuilder() {
CEL_ASSIGN_OR_RETURN(
std::unique_ptr<CompilerBuilder> compiler_builder,
cel::NewCompilerBuilder(descriptor_pool_, compiler_options_));
Expand Down Expand Up @@ -295,8 +154,8 @@ absl::StatusOr<std::unique_ptr<Compiler>> Env::NewCompiler() {
VariableDecl variable_decl;
variable_decl.set_name(variable_config.name);
CEL_ASSIGN_OR_RETURN(Type type,
TypeInfoToType(variable_config.type_info, arena,
descriptor_pool_.get()));
TypeInfoToType(variable_config.type_info,
descriptor_pool_.get(), arena));
variable_decl.set_type(type);
if (variable_config.value.has_value()) {
variable_decl.set_value(variable_config.value);
Expand All @@ -312,7 +171,12 @@ absl::StatusOr<std::unique_ptr<Compiler>> Env::NewCompiler() {
CEL_RETURN_IF_ERROR(checker_builder.AddFunction(function_decl));
}

return compiler_builder->Build();
return compiler_builder;
}

absl::StatusOr<std::unique_ptr<Compiler>> Env::NewCompiler() {
CEL_ASSIGN_OR_RETURN(std::unique_ptr<CompilerBuilder> compiler_builder,
NewCompilerBuilder());
return compiler_builder->Build();
}
} // namespace cel
5 changes: 5 additions & 0 deletions env/env.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ namespace cel {
// customizable CEL features.
class Env {
public:
Env();

// Registers a `CompilerLibrary` with the environment. Note that the library
// does not automatically get added to a `Compiler`. `NewCompiler` relies
// on `Config` to determine which libraries to load.
Expand All @@ -57,6 +59,9 @@ class Env {

void SetConfig(const Config& config) { config_ = config; }

absl::StatusOr<std::unique_ptr<CompilerBuilder>> NewCompilerBuilder();

// Shortcut for NewCompilerBuilder() followed by Build().
absl::StatusOr<std::unique_ptr<Compiler>> NewCompiler();

private:
Expand Down
Loading