Skip to content

Commit 3db277e

Browse files
jnthntatumcopybara-github
authored andcommitted
Make AST fields visible on public AST interface.
PiperOrigin-RevId: 798397862
1 parent 69baabc commit 3db277e

File tree

6 files changed

+144
-132
lines changed

6 files changed

+144
-132
lines changed

common/BUILD

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,15 @@ licenses(["notice"])
2121

2222
cc_library(
2323
name = "ast",
24+
srcs = ["ast.cc"],
2425
hdrs = ["ast.h"],
2526
deps = [
2627
":expr",
28+
"//common/ast:metadata",
29+
"@com_google_absl//absl/base:no_destructor",
30+
"@com_google_absl//absl/base:nullability",
31+
"@com_google_absl//absl/container:flat_hash_map",
32+
"@com_google_absl//absl/strings:string_view",
2733
],
2834
)
2935

common/ast/ast_impl.cc renamed to common/ast.cc

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,50 +12,49 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
#include "common/ast/ast_impl.h"
15+
#include "common/ast.h"
1616

1717
#include <cstdint>
1818

19+
#include "absl/base/no_destructor.h"
1920
#include "absl/base/nullability.h"
20-
#include "absl/container/flat_hash_map.h"
21-
#include "common/ast/expr.h"
2221
#include "common/ast/metadata.h"
2322

24-
namespace cel::ast_internal {
23+
namespace cel {
2524
namespace {
2625

27-
const Type& DynSingleton() {
28-
static auto* singleton = new TypeSpec(TypeKind(DynamicType()));
26+
const TypeSpec& DynSingleton() {
27+
static absl::NoDestructor<TypeSpec> singleton{TypeSpecKind(DynTypeSpec())};
2928
return *singleton;
3029
}
3130

3231
} // namespace
3332

34-
const TypeSpec* absl_nullable AstImpl::GetType(int64_t expr_id) const {
33+
const TypeSpec* absl_nullable Ast::GetType(int64_t expr_id) const {
3534
auto iter = type_map_.find(expr_id);
3635
if (iter == type_map_.end()) {
3736
return nullptr;
3837
}
3938
return &iter->second;
4039
}
4140

42-
const TypeSpec& AstImpl::GetTypeOrDyn(int64_t expr_id) const {
41+
const TypeSpec& Ast::GetTypeOrDyn(int64_t expr_id) const {
4342
if (const TypeSpec* type = GetType(expr_id); type != nullptr) {
4443
return *type;
4544
}
4645
return DynSingleton();
4746
}
4847

49-
const TypeSpec& AstImpl::GetReturnType() const {
48+
const TypeSpec& Ast::GetReturnType() const {
5049
return GetTypeOrDyn(root_expr().id());
5150
}
5251

53-
const Reference* AstImpl::GetReference(int64_t expr_id) const {
52+
const Reference* absl_nullable Ast::GetReference(int64_t expr_id) const {
5453
auto iter = reference_map_.find(expr_id);
5554
if (iter == reference_map_.end()) {
5655
return nullptr;
5756
}
5857
return &iter->second;
5958
}
6059

61-
} // namespace cel::ast_internal
60+
} // namespace cel

common/ast.h

Lines changed: 119 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,38 +15,142 @@
1515
#ifndef THIRD_PARTY_CEL_CPP_COMMON_AST_H_
1616
#define THIRD_PARTY_CEL_CPP_COMMON_AST_H_
1717

18+
#include <cstdint>
19+
#include <string>
20+
#include <utility>
21+
22+
#include "absl/base/nullability.h"
23+
#include "absl/container/flat_hash_map.h"
24+
#include "absl/strings/string_view.h"
25+
#include "common/ast/metadata.h" // IWYU pragma: export
1826
#include "common/expr.h"
1927

2028
namespace cel {
2129

2230
namespace ast_internal {
23-
// Forward declare supported implementations.
2431
class AstImpl;
2532
} // namespace ast_internal
2633

27-
// Runtime representation of a CEL expression's Abstract Syntax Tree.
34+
// In memory representation of a CEL abstract syntax tree.
35+
//
36+
// If AST inspection or manipulation is needed, prefer to use an existing tool
37+
// or traverse the protobuf representation rather than directly manipulating
38+
// through this class. See `cel::NavigableAst` and `cel::AstTraverse`.
2839
//
29-
// This class provides public APIs for CEL users and allows for clients to
30-
// manage lifecycle.
40+
// Type and reference maps are only populated if the AST is checked. Any changes
41+
// to the AST are not automatically reflected in the type or reference maps.
3142
//
32-
// Implementations are intentionally opaque to prevent dependencies on the
33-
// details of the runtime representation. To create a new instance, from a
34-
// protobuf representation, use the conversion utilities in
35-
// `extensions/protobuf/ast_converters.h`.
43+
// To create a new instance from a protobuf representation, use the conversion
44+
// utilities in `common/ast_proto.h`.
3645
class Ast {
3746
public:
47+
using ReferenceMap = absl::flat_hash_map<int64_t, Reference>;
48+
using TypeMap = absl::flat_hash_map<int64_t, TypeSpec>;
49+
3850
virtual ~Ast() = default;
3951

40-
// Whether the AST includes type check information.
41-
// If false, the runtime assumes all types are dyn, and that qualified names
42-
// have not been resolved.
43-
virtual bool IsChecked() const = 0;
52+
Ast() : is_checked_(false) {}
53+
54+
Ast(Expr expr, SourceInfo source_info)
55+
: root_expr_(std::move(expr)),
56+
source_info_(std::move(source_info)),
57+
is_checked_(false) {}
58+
59+
Ast(Expr expr, SourceInfo source_info, ReferenceMap reference_map,
60+
TypeMap type_map, std::string expr_version)
61+
: root_expr_(std::move(expr)),
62+
source_info_(std::move(source_info)),
63+
reference_map_(std::move(reference_map)),
64+
type_map_(std::move(type_map)),
65+
expr_version_(std::move(expr_version)),
66+
is_checked_(true) {}
67+
68+
// Move-only
69+
Ast(const Ast& other) = delete;
70+
Ast& operator=(const Ast& other) = delete;
71+
Ast(Ast&& other) = default;
72+
Ast& operator=(Ast&& other) = default;
73+
74+
// Deprecated. Use `is_checked()` instead.
75+
bool IsChecked() const { return is_checked_; }
76+
77+
bool is_checked() const { return is_checked_; }
78+
void set_is_checked(bool is_checked) { is_checked_ = is_checked; }
79+
80+
// The root expression of the AST.
81+
//
82+
// This is the entry point for evaluation and determines the overall result
83+
// of the expression given a context.
84+
const Expr& root_expr() const { return root_expr_; }
85+
Expr& mutable_root_expr() { return root_expr_; }
86+
87+
// Metadata about the source expression.
88+
const SourceInfo& source_info() const { return source_info_; }
89+
SourceInfo& mutable_source_info() { return source_info_; }
90+
91+
// Returns the type of the expression with the given `expr_id`.
92+
//
93+
// Returns `nullptr` if the expression node is not found or has dynamic type.
94+
const TypeSpec* absl_nullable GetType(int64_t expr_id) const;
95+
const TypeSpec& GetTypeOrDyn(int64_t expr_id) const;
96+
const TypeSpec& GetReturnType() const;
97+
98+
// Returns the resolved reference for the expression with the given `expr_id`.
99+
//
100+
// Returns `nullptr` if the expression node is not found or no reference was
101+
// resolved.
102+
const Reference* absl_nullable GetReference(int64_t expr_id) const;
103+
104+
// A map from expression ids to resolved references.
105+
//
106+
// The following entries are in this table:
107+
//
108+
// - An Ident or Select expression is represented here if it resolves to a
109+
// declaration. For instance, if `a.b.c` is represented by
110+
// `select(select(id(a), b), c)`, and `a.b` resolves to a declaration,
111+
// while `c` is a field selection, then the reference is attached to the
112+
// nested select expression (but not to the id or or the outer select).
113+
// In turn, if `a` resolves to a declaration and `b.c` are field selections,
114+
// the reference is attached to the ident expression.
115+
// - Every Call expression has an entry here, identifying the function being
116+
// called.
117+
// - Every CreateStruct expression for a message has an entry, identifying
118+
// the message.
119+
//
120+
// Unpopulated if the AST is not checked.
121+
const ReferenceMap& reference_map() const { return reference_map_; }
122+
ReferenceMap& mutable_reference_map() { return reference_map_; }
123+
124+
// A map from expression ids to types.
125+
//
126+
// Every expression node which has a type different than DYN has a mapping
127+
// here. If an expression has type DYN, it is omitted from this map to save
128+
// space.
129+
//
130+
// Unpopulated if the AST is not checked.
131+
const TypeMap& type_map() const { return type_map_; }
132+
TypeMap& mutable_type_map() { return type_map_; }
133+
134+
// The expr version indicates the major / minor version number of the `expr`
135+
// representation.
136+
//
137+
// The most common reason for a version change will be to indicate to the CEL
138+
// runtimes that transformations have been performed on the expr during static
139+
// analysis.
140+
absl::string_view expr_version() const { return expr_version_; }
141+
void set_expr_version(absl::string_view expr_version) {
142+
expr_version_ = expr_version;
143+
}
44144

45145
private:
46-
// This interface should only be implemented by friend-visibility allowed
47-
// subclasses.
48-
Ast() = default;
49146
friend class ast_internal::AstImpl;
147+
148+
Expr root_expr_;
149+
SourceInfo source_info_;
150+
ReferenceMap reference_map_;
151+
TypeMap type_map_;
152+
std::string expr_version_;
153+
bool is_checked_;
50154
};
51155

52156
} // namespace cel

common/ast/BUILD

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,17 +75,13 @@ cc_test(
7575

7676
cc_library(
7777
name = "ast_impl",
78-
srcs = ["ast_impl.cc"],
7978
hdrs = ["ast_impl.h"],
8079
deps = [
8180
":expr",
8281
":metadata",
8382
"//common:ast",
8483
"//common:expr",
8584
"//internal:casts",
86-
"@com_google_absl//absl/base:nullability",
87-
"@com_google_absl//absl/container:flat_hash_map",
88-
"@com_google_absl//absl/strings:string_view",
8985
],
9086
)
9187

common/ast/ast_impl.h

Lines changed: 8 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,9 @@
1515
#ifndef THIRD_PARTY_CEL_CPP_BASE_AST_INTERNAL_AST_IMPL_H_
1616
#define THIRD_PARTY_CEL_CPP_BASE_AST_INTERNAL_AST_IMPL_H_
1717

18-
#include <cstdint>
1918
#include <string>
2019
#include <utility>
2120

22-
#include "absl/container/flat_hash_map.h"
23-
#include "absl/strings/string_view.h"
2421
#include "common/ast.h"
2522
#include "common/ast/expr.h"
2623
#include "common/ast/metadata.h" // IWYU pragma: export
@@ -29,18 +26,13 @@
2926

3027
namespace cel::ast_internal {
3128

32-
// In memory representation of a CEL abstract syntax tree.
29+
// Trivial subclass of the public Ast.
3330
//
34-
// If AST inspection or manipulation is needed, prefer to use an existing tool
35-
// or traverse the protobuf representation rather than directly manipulating
36-
// through this class. See `cel::NavigableAst` and `cel::AstTraverse`.
37-
//
38-
// Type and reference maps are only populated if the AST is checked. Any changes
39-
// to the AST are not automatically reflected in the type or reference maps.
31+
// Temporarily needed to transition to just using the public Ast.
4032
class AstImpl : public Ast {
4133
public:
42-
using ReferenceMap = absl::flat_hash_map<int64_t, Reference>;
43-
using TypeMap = absl::flat_hash_map<int64_t, Type>;
34+
using ReferenceMap = Ast::ReferenceMap;
35+
using TypeMap = Ast::TypeMap;
4436

4537
// Overloads for down casting from the public interface to the internal
4638
// implementation.
@@ -60,106 +52,21 @@ class AstImpl : public Ast {
6052
return cel::internal::down_cast<const AstImpl*>(ast);
6153
}
6254

63-
AstImpl() : is_checked_(false) {}
55+
AstImpl() = default;
6456

6557
AstImpl(Expr expr, SourceInfo source_info)
66-
: root_expr_(std::move(expr)),
67-
source_info_(std::move(source_info)),
68-
is_checked_(false) {}
58+
: Ast(std::move(expr), std::move(source_info)) {}
6959

7060
AstImpl(Expr expr, SourceInfo source_info, ReferenceMap reference_map,
7161
TypeMap type_map, std::string expr_version)
72-
: root_expr_(std::move(expr)),
73-
source_info_(std::move(source_info)),
74-
reference_map_(std::move(reference_map)),
75-
type_map_(std::move(type_map)),
76-
expr_version_(std::move(expr_version)),
77-
is_checked_(true) {}
62+
: Ast(std::move(expr), std::move(source_info), std::move(reference_map),
63+
std::move(type_map), std::move(expr_version)) {}
7864

7965
// Move-only
8066
AstImpl(const AstImpl& other) = delete;
8167
AstImpl& operator=(const AstImpl& other) = delete;
8268
AstImpl(AstImpl&& other) = default;
8369
AstImpl& operator=(AstImpl&& other) = default;
84-
85-
// Implement public Ast APIs.
86-
bool IsChecked() const override { return is_checked_; }
87-
88-
bool is_checked() const { return is_checked_; }
89-
void set_is_checked(bool is_checked) { is_checked_ = is_checked; }
90-
91-
// The root expression of the AST.
92-
//
93-
// This is the entry point for evaluation and determines the overall result
94-
// of the expression given a context.
95-
const Expr& root_expr() const { return root_expr_; }
96-
Expr& mutable_root_expr() { return root_expr_; }
97-
98-
// Metadata about the source expression.
99-
const SourceInfo& source_info() const { return source_info_; }
100-
SourceInfo& mutable_source_info() { return source_info_; }
101-
102-
// Returns the type of the expression with the given `expr_id`.
103-
//
104-
// Returns `nullptr` if the expression node is not found or has dynamic type.
105-
const TypeSpec* absl_nullable GetType(int64_t expr_id) const;
106-
const TypeSpec& GetTypeOrDyn(int64_t expr_id) const;
107-
const TypeSpec& GetReturnType() const;
108-
109-
// Returns the resolved reference for the expression with the given `expr_id`.
110-
//
111-
// Returns `nullptr` if the expression node is not found or no reference was
112-
// resolved.
113-
const Reference* absl_nullable GetReference(int64_t expr_id) const;
114-
115-
// A map from expression ids to resolved references.
116-
//
117-
// The following entries are in this table:
118-
//
119-
// - An Ident or Select expression is represented here if it resolves to a
120-
// declaration. For instance, if `a.b.c` is represented by
121-
// `select(select(id(a), b), c)`, and `a.b` resolves to a declaration,
122-
// while `c` is a field selection, then the reference is attached to the
123-
// nested select expression (but not to the id or or the outer select).
124-
// In turn, if `a` resolves to a declaration and `b.c` are field selections,
125-
// the reference is attached to the ident expression.
126-
// - Every Call expression has an entry here, identifying the function being
127-
// called.
128-
// - Every CreateStruct expression for a message has an entry, identifying
129-
// the message.
130-
//
131-
// Unpopulated if the AST is not checked.
132-
const ReferenceMap& reference_map() const { return reference_map_; }
133-
ReferenceMap& mutable_reference_map() { return reference_map_; }
134-
135-
// A map from expression ids to types.
136-
//
137-
// Every expression node which has a type different than DYN has a mapping
138-
// here. If an expression has type DYN, it is omitted from this map to save
139-
// space.
140-
//
141-
// Unpopulated if the AST is not checked.
142-
const TypeMap& type_map() const { return type_map_; }
143-
TypeMap& mutable_type_map() { return type_map_; }
144-
145-
// The expr version indicates the major / minor version number of the `expr`
146-
// representation.
147-
//
148-
// The most common reason for a version change will be to indicate to the CEL
149-
// runtimes that transformations have been performed on the expr during static
150-
// analysis.
151-
absl::string_view expr_version() const { return expr_version_; }
152-
void set_expr_version(absl::string_view expr_version) {
153-
expr_version_ = expr_version;
154-
}
155-
156-
private:
157-
Expr root_expr_;
158-
SourceInfo source_info_;
159-
ReferenceMap reference_map_;
160-
TypeMap type_map_;
161-
std::string expr_version_;
162-
bool is_checked_;
16370
};
16471

16572
} // namespace cel::ast_internal

0 commit comments

Comments
 (0)