Skip to content
Merged
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
91 changes: 35 additions & 56 deletions checker/internal/type_check_env.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,25 +34,18 @@ namespace cel::checker_internal {

const VariableDecl* absl_nullable TypeCheckEnv::LookupVariable(
absl::string_view name) const {
const TypeCheckEnv* scope = this;
while (scope != nullptr) {
if (auto it = scope->variables_.find(name); it != scope->variables_.end()) {
return &it->second;
}
scope = scope->parent_;
if (auto it = variables_.find(name); it != variables_.end()) {
return &it->second;
}
return nullptr;
}

const FunctionDecl* absl_nullable TypeCheckEnv::LookupFunction(
absl::string_view name) const {
const TypeCheckEnv* scope = this;
while (scope != nullptr) {
if (auto it = scope->functions_.find(name); it != scope->functions_.end()) {
return &it->second;
}
scope = scope->parent_;
if (auto it = functions_.find(name); it != functions_.end()) {
return &it->second;
}

return nullptr;
}

Expand All @@ -71,17 +64,13 @@ absl::StatusOr<absl::optional<Type>> TypeCheckEnv::LookupTypeName(
return Type::Enum(enum_descriptor);
}
}
const TypeCheckEnv* scope = this;
do {
for (auto iter = type_providers_.rbegin(); iter != type_providers_.rend();
++iter) {
auto type = (*iter)->FindType(name);
if (!type.ok() || type->has_value()) {
return type;
}
for (auto iter = type_providers_.rbegin(); iter != type_providers_.rend();
++iter) {
auto type = (*iter)->FindType(name);
if (!type.ok() || type->has_value()) {
return type;
}
scope = scope->parent_;
} while ((scope != nullptr));
}
return absl::nullopt;
}

Expand All @@ -106,26 +95,21 @@ absl::StatusOr<absl::optional<VariableDecl>> TypeCheckEnv::LookupEnumConstant(
return decl;
}
}
const TypeCheckEnv* scope = this;
do {
for (auto iter = type_providers_.rbegin(); iter != type_providers_.rend();
++iter) {
auto enum_constant = (*iter)->FindEnumConstant(type, value);
if (!enum_constant.ok()) {
return enum_constant.status();
}
if (enum_constant->has_value()) {
auto decl =
MakeVariableDecl(absl::StrCat((**enum_constant).type_full_name, ".",
(**enum_constant).value_name),
(**enum_constant).type);
decl.set_value(
Constant(static_cast<int64_t>((**enum_constant).number)));
return decl;
}
for (auto iter = type_providers_.rbegin(); iter != type_providers_.rend();
++iter) {
auto enum_constant = (*iter)->FindEnumConstant(type, value);
if (!enum_constant.ok()) {
return enum_constant.status();
}
scope = scope->parent_;
} while (scope != nullptr);
if (enum_constant->has_value()) {
auto decl =
MakeVariableDecl(absl::StrCat((**enum_constant).type_full_name, ".",
(**enum_constant).value_name),
(**enum_constant).type);
decl.set_value(Constant(static_cast<int64_t>((**enum_constant).number)));
return decl;
}
}
return absl::nullopt;
}

Expand Down Expand Up @@ -165,22 +149,17 @@ absl::StatusOr<absl::optional<StructTypeField>> TypeCheckEnv::LookupStructField(
return cel::MessageTypeField(field_descriptor);
}
}
const TypeCheckEnv* scope = this;
do {
// Check the type providers in reverse registration order.
// Note: this doesn't allow for shadowing a type with a subset type of the
// same name -- the parent type provider will still be considered when
// checking field accesses.
for (auto iter = type_providers_.rbegin(); iter != type_providers_.rend();
++iter) {
auto field_info =
(*iter)->FindStructTypeFieldByName(type_name, field_name);
if (!field_info.ok() || field_info->has_value()) {
return field_info;
}
// Check the type providers in reverse registration order.
// Note: this doesn't allow for shadowing a type with a subset type of the
// same name -- the prior type provider will still be considered when
// checking field accesses.
for (auto iter = type_providers_.rbegin(); iter != type_providers_.rend();
++iter) {
auto field_info = (*iter)->FindStructTypeFieldByName(type_name, field_name);
if (!field_info.ok() || field_info->has_value()) {
return field_info;
}
scope = scope->parent_;
} while (scope != nullptr);
}
return absl::nullopt;
}

Expand Down
20 changes: 2 additions & 18 deletions checker/internal/type_check_env.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,17 +89,14 @@ class TypeCheckEnv {
explicit TypeCheckEnv(
absl_nonnull std::shared_ptr<const google::protobuf::DescriptorPool>
descriptor_pool)
: descriptor_pool_(std::move(descriptor_pool)),
container_(""),
parent_(nullptr) {}
: descriptor_pool_(std::move(descriptor_pool)), container_("") {}

TypeCheckEnv(absl_nonnull std::shared_ptr<const google::protobuf::DescriptorPool>
descriptor_pool,
std::shared_ptr<google::protobuf::Arena> arena)
: descriptor_pool_(std::move(descriptor_pool)),
arena_(std::move(arena)),
container_(""),
parent_(nullptr) {}
container_("") {}

// Move-only.
TypeCheckEnv(TypeCheckEnv&&) = default;
Expand Down Expand Up @@ -163,9 +160,6 @@ class TypeCheckEnv {
functions_[decl.name()] = std::move(decl);
}

const TypeCheckEnv* absl_nullable parent() const { return parent_; }
void set_parent(TypeCheckEnv* parent) { parent_ = parent; }

// Returns the declaration for the given name if it is found in the current
// or any parent scope.
// Note: the returned declaration ptr is only valid as long as no changes are
Expand All @@ -184,10 +178,6 @@ class TypeCheckEnv {
absl::StatusOr<absl::optional<VariableDecl>> LookupTypeConstant(
google::protobuf::Arena* absl_nonnull arena, absl::string_view type_name) const;

TypeCheckEnv MakeExtendedEnvironment() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return TypeCheckEnv(this);
}

const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool() const {
return descriptor_pool_.get();
}
Expand All @@ -200,19 +190,13 @@ class TypeCheckEnv {
}

private:
explicit TypeCheckEnv(const TypeCheckEnv* absl_nonnull parent)
: descriptor_pool_(parent->descriptor_pool_),
container_(parent != nullptr ? parent->container() : ""),
parent_(parent) {}

absl::StatusOr<absl::optional<VariableDecl>> LookupEnumConstant(
absl::string_view type, absl::string_view value) const;

absl_nonnull std::shared_ptr<const google::protobuf::DescriptorPool> descriptor_pool_;
// If set, an arena was needed to allocate types in the environment.
absl_nullable std::shared_ptr<const google::protobuf::Arena> arena_;
std::string container_;
const TypeCheckEnv* absl_nullable parent_;

// Maps fully qualified names to declarations.
absl::flat_hash_map<std::string, VariableDecl> variables_;
Expand Down