diff --git a/tools/BUILD b/tools/BUILD index a409958d8..2849bc919 100644 --- a/tools/BUILD +++ b/tools/BUILD @@ -51,6 +51,7 @@ cc_library( "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/log:absl_check", "@com_google_absl//absl/memory", + "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/types:span", "@com_google_googleapis//google/api/expr/v1alpha1:checked_cc_proto", "@com_google_googleapis//google/api/expr/v1alpha1:syntax_cc_proto", @@ -65,6 +66,8 @@ cc_test( "//base:builtins", "//internal:testing", "//parser", + "@com_google_absl//absl/base", + "@com_google_absl//absl/strings", "@com_google_googleapis//google/api/expr/v1alpha1:syntax_cc_proto", ], ) diff --git a/tools/navigable_ast.cc b/tools/navigable_ast.cc index 368c366a1..afac5dac2 100644 --- a/tools/navigable_ast.cc +++ b/tools/navigable_ast.cc @@ -23,6 +23,7 @@ #include "absl/container/flat_hash_map.h" #include "absl/log/absl_check.h" #include "absl/memory/memory.h" +#include "absl/strings/string_view.h" #include "absl/types/span.h" #include "eval/public/ast_traverse.h" #include "eval/public/ast_visitor.h" @@ -185,6 +186,64 @@ class NavigableExprBuilderVisitor } // namespace +absl::string_view ChildKindName(ChildKind kind) { + switch (kind) { + case ChildKind::kUnspecified: + return "Unspecified"; + case ChildKind::kSelectOperand: + return "SelectOperand"; + case ChildKind::kCallReceiver: + return "CallReceiver"; + case ChildKind::kCallArg: + return "CallArg"; + case ChildKind::kListElem: + return "ListElem"; + case ChildKind::kMapKey: + return "MapKey"; + case ChildKind::kMapValue: + return "MapValue"; + case ChildKind::kStructValue: + return "StructValue"; + case ChildKind::kComprehensionRange: + return "ComprehensionRange"; + case ChildKind::kComprehensionInit: + return "ComprehensionInit"; + case ChildKind::kComprehensionCondition: + return "ComprehensionCondition"; + case ChildKind::kComprehensionLoopStep: + return "ComprehensionLoopStep"; + case ChildKind::kComprensionResult: + return "ComprehensionResult"; + default: + return "Unknown ChildKind"; + } +} + +absl::string_view NodeKindName(NodeKind kind) { + switch (kind) { + case NodeKind::kUnspecified: + return "Unspecified"; + case NodeKind::kConstant: + return "Constant"; + case NodeKind::kIdent: + return "Ident"; + case NodeKind::kSelect: + return "Select"; + case NodeKind::kCall: + return "Call"; + case NodeKind::kList: + return "List"; + case NodeKind::kMap: + return "Map"; + case NodeKind::kStruct: + return "Struct"; + case NodeKind::kComprehension: + return "Comprehension"; + default: + return "Unknown NodeKind"; + } +} + int AstNode::child_index() const { if (data_.parent == nullptr) { return -1; diff --git a/tools/navigable_ast.h b/tools/navigable_ast.h index 1a78bb70d..321866cbf 100644 --- a/tools/navigable_ast.h +++ b/tools/navigable_ast.h @@ -24,6 +24,7 @@ #include "google/api/expr/v1alpha1/syntax.pb.h" #include "absl/base/nullability.h" #include "absl/container/flat_hash_map.h" +#include "absl/strings/string_view.h" #include "absl/types/span.h" #include "tools/internal/navigable_ast_internal.h" @@ -57,6 +58,20 @@ enum class NodeKind { kComprehension, }; +absl::string_view ChildKindName(ChildKind kind); + +template +void AbslStringify(Sink& sink, ChildKind kind) { + absl::Format(&sink, "%s", ChildKindName(kind)); +} + +absl::string_view NodeKindName(NodeKind kind); + +template +void AbslStringify(Sink& sink, NodeKind kind) { + absl::Format(&sink, "%s", NodeKindName(kind)); +} + class AstNode; namespace tools_internal { diff --git a/tools/navigable_ast_test.cc b/tools/navigable_ast_test.cc index bb8a8a667..36b1379d8 100644 --- a/tools/navigable_ast_test.cc +++ b/tools/navigable_ast_test.cc @@ -18,6 +18,8 @@ #include #include "google/api/expr/v1alpha1/syntax.pb.h" +#include "absl/base/casts.h" +#include "absl/strings/str_cat.h" #include "base/builtins.h" #include "internal/testing.h" #include "parser/parser.h" @@ -340,5 +342,43 @@ TEST(NavigableAst, DescendantsPreorderCreateMap) { Pair(NodeKind::kConstant, ChildKind::kMapValue))); } +TEST(NodeKind, Stringify) { + // Note: the specific values are not important or guaranteed to be stable, + // they are only intended to make test outputs clearer. + EXPECT_EQ(absl::StrCat(NodeKind::kConstant), "Constant"); + EXPECT_EQ(absl::StrCat(NodeKind::kIdent), "Ident"); + EXPECT_EQ(absl::StrCat(NodeKind::kSelect), "Select"); + EXPECT_EQ(absl::StrCat(NodeKind::kCall), "Call"); + EXPECT_EQ(absl::StrCat(NodeKind::kList), "List"); + EXPECT_EQ(absl::StrCat(NodeKind::kMap), "Map"); + EXPECT_EQ(absl::StrCat(NodeKind::kStruct), "Struct"); + EXPECT_EQ(absl::StrCat(NodeKind::kComprehension), "Comprehension"); + EXPECT_EQ(absl::StrCat(NodeKind::kUnspecified), "Unspecified"); + + EXPECT_EQ(absl::StrCat(absl::bit_cast(255)), "Unknown NodeKind"); +} + +TEST(ChildKind, Stringify) { + // Note: the specific values are not important or guaranteed to be stable, + // they are only intended to make test outputs clearer. + EXPECT_EQ(absl::StrCat(ChildKind::kSelectOperand), "SelectOperand"); + EXPECT_EQ(absl::StrCat(ChildKind::kCallReceiver), "CallReceiver"); + EXPECT_EQ(absl::StrCat(ChildKind::kCallArg), "CallArg"); + EXPECT_EQ(absl::StrCat(ChildKind::kListElem), "ListElem"); + EXPECT_EQ(absl::StrCat(ChildKind::kMapKey), "MapKey"); + EXPECT_EQ(absl::StrCat(ChildKind::kMapValue), "MapValue"); + EXPECT_EQ(absl::StrCat(ChildKind::kStructValue), "StructValue"); + EXPECT_EQ(absl::StrCat(ChildKind::kComprehensionRange), "ComprehensionRange"); + EXPECT_EQ(absl::StrCat(ChildKind::kComprehensionInit), "ComprehensionInit"); + EXPECT_EQ(absl::StrCat(ChildKind::kComprehensionCondition), + "ComprehensionCondition"); + EXPECT_EQ(absl::StrCat(ChildKind::kComprehensionLoopStep), + "ComprehensionLoopStep"); + EXPECT_EQ(absl::StrCat(ChildKind::kComprensionResult), "ComprehensionResult"); + EXPECT_EQ(absl::StrCat(ChildKind::kUnspecified), "Unspecified"); + + EXPECT_EQ(absl::StrCat(absl::bit_cast(255)), "Unknown ChildKind"); +} + } // namespace } // namespace cel