Skip to content

Commit f739b8a

Browse files
jnthntatumcopybara-github
authored andcommitted
Factor out and consolidate internals for NavigableAst implementation in common_internal.
PiperOrigin-RevId: 798362130
1 parent 3ad63cd commit f739b8a

File tree

11 files changed

+400
-365
lines changed

11 files changed

+400
-365
lines changed

common/ast/BUILD

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,3 +151,32 @@ cc_test(
151151
"@com_google_absl//absl/types:variant",
152152
],
153153
)
154+
155+
cc_library(
156+
name = "navigable_ast_internal",
157+
srcs = ["navigable_ast_kinds.cc"],
158+
hdrs = [
159+
"navigable_ast_internal.h",
160+
"navigable_ast_kinds.h",
161+
],
162+
deps = [
163+
"@com_google_absl//absl/base:nullability",
164+
"@com_google_absl//absl/container:flat_hash_map",
165+
"@com_google_absl//absl/log:absl_check",
166+
"@com_google_absl//absl/strings",
167+
"@com_google_absl//absl/strings:str_format",
168+
"@com_google_absl//absl/types:span",
169+
],
170+
)
171+
172+
cc_test(
173+
name = "navigable_ast_internal_test",
174+
srcs = ["navigable_ast_internal_test.cc"],
175+
deps = [
176+
":navigable_ast_internal",
177+
"//internal:testing",
178+
"@com_google_absl//absl/base",
179+
"@com_google_absl//absl/strings",
180+
"@com_google_absl//absl/types:span",
181+
],
182+
)

tools/internal/navigable_ast_internal.h renamed to common/ast/navigable_ast_internal.h

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,23 @@
1111
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
14-
#ifndef THIRD_PARTY_CEL_CPP_TOOLS_INTERNAL_NAVIGABLE_AST_INTERNAL_H_
15-
#define THIRD_PARTY_CEL_CPP_TOOLS_INTERNAL_NAVIGABLE_AST_INTERNAL_H_
14+
#ifndef THIRD_PARTY_CEL_CPP_COMMON_AST_NAVIGABLE_AST_INTERNAL_H_
15+
#define THIRD_PARTY_CEL_CPP_COMMON_AST_NAVIGABLE_AST_INTERNAL_H_
1616

1717
#include <cstddef>
18+
#include <cstdint>
1819
#include <iterator>
20+
#include <memory>
1921
#include <type_traits>
22+
#include <vector>
2023

24+
#include "absl/base/nullability.h"
25+
#include "absl/container/flat_hash_map.h"
2126
#include "absl/log/absl_check.h"
2227
#include "absl/types/span.h"
28+
#include "common/ast/navigable_ast_kinds.h" // IWYU pragma: keep
2329

24-
namespace cel::tools_internal {
30+
namespace cel::common_internal {
2531

2632
// Implementation for range used for traversals backed by an absl::Span.
2733
//
@@ -106,6 +112,55 @@ class NavigableAstRange {
106112
SpanType span_;
107113
};
108114

109-
} // namespace cel::tools_internal
115+
template <typename AstNode>
116+
struct NavigableAstMetadata;
110117

111-
#endif // THIRD_PARTY_CEL_CPP_TOOLS_INTERNAL_NAVIGABLE_AST_INTERNAL_H_
118+
// Internal implementation for data-structures handling cross-referencing nodes.
119+
//
120+
// This is exposed separately to allow building up the AST relationships
121+
// without exposing too much mutable state on the client facing classes.
122+
template <typename AstNode>
123+
struct NavigableAstNodeData {
124+
AstNode* parent;
125+
const typename AstNode::ExprType* expr;
126+
ChildKind parent_relation;
127+
NodeKind node_kind;
128+
const NavigableAstMetadata<AstNode>* absl_nonnull metadata;
129+
size_t index;
130+
size_t tree_size;
131+
size_t height;
132+
int child_index;
133+
std::vector<AstNode*> children;
134+
};
135+
136+
template <typename AstNode>
137+
struct NavigableAstMetadata {
138+
// The nodes in the AST in preorder.
139+
//
140+
// unique_ptr is used to guarantee pointer stability in the other tables.
141+
std::vector<std::unique_ptr<AstNode>> nodes;
142+
std::vector<const AstNode* absl_nonnull> postorder;
143+
absl::flat_hash_map<int64_t, const AstNode* absl_nonnull> id_to_node;
144+
absl::flat_hash_map<const typename AstNode::ExprType*,
145+
const AstNode* absl_nonnull>
146+
expr_to_node;
147+
};
148+
149+
template <typename AstNode>
150+
struct PostorderTraits {
151+
using UnderlyingType = const AstNode*;
152+
153+
static const AstNode& Adapt(const AstNode* const node) { return *node; }
154+
};
155+
156+
template <typename AstNode>
157+
struct PreorderTraits {
158+
using UnderlyingType = std::unique_ptr<AstNode>;
159+
static const AstNode& Adapt(const std::unique_ptr<AstNode>& node) {
160+
return *node;
161+
}
162+
};
163+
164+
} // namespace cel::common_internal
165+
166+
#endif // THIRD_PARTY_CEL_CPP_COMMON_AST_NAVIGABLE_AST_INTERNAL_H_
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
#include "common/ast/navigable_ast_internal.h"
15+
16+
#include <iterator>
17+
#include <vector>
18+
19+
#include "absl/base/casts.h"
20+
#include "absl/strings/str_cat.h"
21+
#include "absl/types/span.h"
22+
#include "common/ast/navigable_ast_kinds.h"
23+
#include "internal/testing.h"
24+
25+
namespace cel::common_internal {
26+
namespace {
27+
28+
struct TestRangeTraits {
29+
using UnderlyingType = int;
30+
static double Adapt(const UnderlyingType& value) {
31+
return static_cast<double>(value) + 0.5;
32+
}
33+
};
34+
35+
TEST(NavigableAstRangeTest, BasicIteration) {
36+
std::vector<int> values{1, 2, 3};
37+
NavigableAstRange<TestRangeTraits> range(absl::MakeConstSpan(values));
38+
absl::Span<const int> span(values);
39+
auto it = range.begin();
40+
EXPECT_EQ(*it, 1.5);
41+
EXPECT_EQ(*++it, 2.5);
42+
EXPECT_EQ(*++it, 3.5);
43+
EXPECT_EQ(++it, range.end());
44+
EXPECT_EQ(*--it, 3.5);
45+
EXPECT_EQ(*--it, 2.5);
46+
EXPECT_EQ(*--it, 1.5);
47+
EXPECT_EQ(it, range.begin());
48+
}
49+
50+
TEST(NodeKind, Stringify) {
51+
// Note: the specific values are not important or guaranteed to be stable,
52+
// they are only intended to make test outputs clearer.
53+
EXPECT_EQ(absl::StrCat(NodeKind::kConstant), "Constant");
54+
EXPECT_EQ(absl::StrCat(NodeKind::kIdent), "Ident");
55+
EXPECT_EQ(absl::StrCat(NodeKind::kSelect), "Select");
56+
EXPECT_EQ(absl::StrCat(NodeKind::kCall), "Call");
57+
EXPECT_EQ(absl::StrCat(NodeKind::kList), "List");
58+
EXPECT_EQ(absl::StrCat(NodeKind::kMap), "Map");
59+
EXPECT_EQ(absl::StrCat(NodeKind::kStruct), "Struct");
60+
EXPECT_EQ(absl::StrCat(NodeKind::kComprehension), "Comprehension");
61+
EXPECT_EQ(absl::StrCat(NodeKind::kUnspecified), "Unspecified");
62+
63+
EXPECT_EQ(absl::StrCat(absl::bit_cast<NodeKind>(255)),
64+
"Unknown NodeKind 255");
65+
}
66+
67+
TEST(ChildKind, Stringify) {
68+
// Note: the specific values are not important or guaranteed to be stable,
69+
// they are only intended to make test outputs clearer.
70+
EXPECT_EQ(absl::StrCat(ChildKind::kSelectOperand), "SelectOperand");
71+
EXPECT_EQ(absl::StrCat(ChildKind::kCallReceiver), "CallReceiver");
72+
EXPECT_EQ(absl::StrCat(ChildKind::kCallArg), "CallArg");
73+
EXPECT_EQ(absl::StrCat(ChildKind::kListElem), "ListElem");
74+
EXPECT_EQ(absl::StrCat(ChildKind::kMapKey), "MapKey");
75+
EXPECT_EQ(absl::StrCat(ChildKind::kMapValue), "MapValue");
76+
EXPECT_EQ(absl::StrCat(ChildKind::kStructValue), "StructValue");
77+
EXPECT_EQ(absl::StrCat(ChildKind::kComprehensionRange), "ComprehensionRange");
78+
EXPECT_EQ(absl::StrCat(ChildKind::kComprehensionInit), "ComprehensionInit");
79+
EXPECT_EQ(absl::StrCat(ChildKind::kComprehensionCondition),
80+
"ComprehensionCondition");
81+
EXPECT_EQ(absl::StrCat(ChildKind::kComprehensionLoopStep),
82+
"ComprehensionLoopStep");
83+
EXPECT_EQ(absl::StrCat(ChildKind::kComprensionResult), "ComprehensionResult");
84+
EXPECT_EQ(absl::StrCat(ChildKind::kUnspecified), "Unspecified");
85+
86+
EXPECT_EQ(absl::StrCat(absl::bit_cast<ChildKind>(255)),
87+
"Unknown ChildKind 255");
88+
}
89+
90+
} // namespace
91+
} // namespace cel::common_internal

common/ast/navigable_ast_kinds.cc

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
#include "common/ast/navigable_ast_kinds.h"
15+
16+
#include <string>
17+
18+
#include "absl/strings/str_cat.h"
19+
20+
namespace cel {
21+
22+
std::string ChildKindName(ChildKind kind) {
23+
switch (kind) {
24+
case ChildKind::kUnspecified:
25+
return "Unspecified";
26+
case ChildKind::kSelectOperand:
27+
return "SelectOperand";
28+
case ChildKind::kCallReceiver:
29+
return "CallReceiver";
30+
case ChildKind::kCallArg:
31+
return "CallArg";
32+
case ChildKind::kListElem:
33+
return "ListElem";
34+
case ChildKind::kMapKey:
35+
return "MapKey";
36+
case ChildKind::kMapValue:
37+
return "MapValue";
38+
case ChildKind::kStructValue:
39+
return "StructValue";
40+
case ChildKind::kComprehensionRange:
41+
return "ComprehensionRange";
42+
case ChildKind::kComprehensionInit:
43+
return "ComprehensionInit";
44+
case ChildKind::kComprehensionCondition:
45+
return "ComprehensionCondition";
46+
case ChildKind::kComprehensionLoopStep:
47+
return "ComprehensionLoopStep";
48+
case ChildKind::kComprensionResult:
49+
return "ComprehensionResult";
50+
default:
51+
return absl::StrCat("Unknown ChildKind ", static_cast<int>(kind));
52+
}
53+
}
54+
55+
std::string NodeKindName(NodeKind kind) {
56+
switch (kind) {
57+
case NodeKind::kUnspecified:
58+
return "Unspecified";
59+
case NodeKind::kConstant:
60+
return "Constant";
61+
case NodeKind::kIdent:
62+
return "Ident";
63+
case NodeKind::kSelect:
64+
return "Select";
65+
case NodeKind::kCall:
66+
return "Call";
67+
case NodeKind::kList:
68+
return "List";
69+
case NodeKind::kMap:
70+
return "Map";
71+
case NodeKind::kStruct:
72+
return "Struct";
73+
case NodeKind::kComprehension:
74+
return "Comprehension";
75+
default:
76+
return absl::StrCat("Unknown NodeKind ", static_cast<int>(kind));
77+
}
78+
}
79+
80+
} // namespace cel

common/ast/navigable_ast_kinds.h

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
// IWYU pragma: private
15+
#ifndef THIRD_PARTY_CEL_CPP_COMMON_AST_NAVIGABLE_AST_KINDS_H_
16+
#define THIRD_PARTY_CEL_CPP_COMMON_AST_NAVIGABLE_AST_KINDS_H_
17+
18+
#include <string>
19+
20+
#include "absl/strings/str_format.h"
21+
22+
namespace cel {
23+
24+
// The traversal relationship from parent to the given node in a NavigableAst.
25+
enum class ChildKind {
26+
kUnspecified,
27+
kSelectOperand,
28+
kCallReceiver,
29+
kCallArg,
30+
kListElem,
31+
kMapKey,
32+
kMapValue,
33+
kStructValue,
34+
kComprehensionRange,
35+
kComprehensionInit,
36+
kComprehensionCondition,
37+
kComprehensionLoopStep,
38+
kComprensionResult
39+
};
40+
41+
// The type of the node in a NavigableAst.
42+
enum class NodeKind {
43+
kUnspecified,
44+
kConstant,
45+
kIdent,
46+
kSelect,
47+
kCall,
48+
kList,
49+
kMap,
50+
kStruct,
51+
kComprehension,
52+
};
53+
54+
// Human readable ChildKind name. Provided for test readability -- do not depend
55+
// on the specific values.
56+
std::string ChildKindName(ChildKind kind);
57+
58+
template <typename Sink>
59+
void AbslStringify(Sink& sink, ChildKind kind) {
60+
absl::Format(&sink, "%s", ChildKindName(kind));
61+
}
62+
63+
// Human readable NodeKind name. Provided for test readability -- do not depend
64+
// on the specific values.
65+
std::string NodeKindName(NodeKind kind);
66+
67+
template <typename Sink>
68+
void AbslStringify(Sink& sink, NodeKind kind) {
69+
absl::Format(&sink, "%s", NodeKindName(kind));
70+
}
71+
72+
} // namespace cel
73+
74+
#endif // THIRD_PARTY_CEL_CPP_COMMON_AST_NAVIGABLE_AST_KINDS_H_

tools/BUILD

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,16 +71,15 @@ cc_library(
7171
srcs = ["navigable_ast.cc"],
7272
hdrs = ["navigable_ast.h"],
7373
deps = [
74+
"//common/ast:navigable_ast_internal",
7475
"//eval/public:ast_traverse",
7576
"//eval/public:ast_visitor",
7677
"//eval/public:ast_visitor_base",
7778
"//eval/public:source_position",
78-
"//tools/internal:navigable_ast_internal",
7979
"@com_google_absl//absl/base:nullability",
8080
"@com_google_absl//absl/container:flat_hash_map",
81-
"@com_google_absl//absl/log:absl_check",
81+
"@com_google_absl//absl/functional:any_invocable",
8282
"@com_google_absl//absl/memory",
83-
"@com_google_absl//absl/strings",
8483
"@com_google_absl//absl/types:span",
8584
"@com_google_cel_spec//proto/cel/expr:checked_cc_proto",
8685
"@com_google_cel_spec//proto/cel/expr:syntax_cc_proto",
@@ -95,8 +94,6 @@ cc_test(
9594
"//base:builtins",
9695
"//internal:testing",
9796
"//parser",
98-
"@com_google_absl//absl/base",
99-
"@com_google_absl//absl/strings",
10097
"@com_google_cel_spec//proto/cel/expr:syntax_cc_proto",
10198
],
10299
)

0 commit comments

Comments
 (0)