diff --git a/p4_constraints/ast.cc b/p4_constraints/ast.cc index 445dcad..e6dc8be 100644 --- a/p4_constraints/ast.cc +++ b/p4_constraints/ast.cc @@ -205,30 +205,31 @@ bool HaveSameSource(const SourceLocation& source_location_1, return gutils::ProtoEqual(source_location_1, source_location_2, differ); } -// Populates `field_set` with the fields used in `expr`. -void AddMatchFields(const ast::Expression& expr, - absl::flat_hash_set& field_set) { +// Populates `variable_set` with the variables used in `expr`. +void AddVariables(const ast::Expression& expr, + absl::flat_hash_set& variable_set) { switch (expr.expression_case()) { case ast::Expression::kKey: - field_set.insert(expr.key()); + variable_set.insert(expr.key()); return; case ast::Expression::kActionParameter: + variable_set.insert(expr.action_parameter()); return; case ast::Expression::kBooleanNegation: - AddMatchFields(expr.boolean_negation(), field_set); + AddVariables(expr.boolean_negation(), variable_set); return; case ast::Expression::kArithmeticNegation: - AddMatchFields(expr.arithmetic_negation(), field_set); + AddVariables(expr.arithmetic_negation(), variable_set); return; case ast::Expression::kTypeCast: - AddMatchFields(expr.type_cast(), field_set); + AddVariables(expr.type_cast(), variable_set); return; case ast::Expression::kBinaryExpression: - AddMatchFields(expr.binary_expression().left(), field_set); - AddMatchFields(expr.binary_expression().right(), field_set); + AddVariables(expr.binary_expression().left(), variable_set); + AddVariables(expr.binary_expression().right(), variable_set); return; case ast::Expression::kFieldAccess: - AddMatchFields(expr.field_access().expr(), field_set); + AddVariables(expr.field_access().expr(), variable_set); return; // Currently priority is the only metadata and that is not a key. case ast::Expression::kAttributeAccess: @@ -242,9 +243,9 @@ void AddMatchFields(const ast::Expression& expr, } } -absl::flat_hash_set GetMatchFields(const ast::Expression& expr) { +absl::flat_hash_set GetVariables(const ast::Expression& expr) { absl::flat_hash_set field_set; - AddMatchFields(expr, field_set); + AddVariables(expr, field_set); return field_set; } diff --git a/p4_constraints/ast.h b/p4_constraints/ast.h index a256d5f..1d064cb 100644 --- a/p4_constraints/ast.h +++ b/p4_constraints/ast.h @@ -73,8 +73,10 @@ Type TypeCaseToType(Type::TypeCase type_case); bool HaveSameSource(const SourceLocation& source_location_1, const SourceLocation& source_location_2); -// Returns a set containing the `fields` present in `expr`. -absl::flat_hash_set GetMatchFields(const ast::Expression& expr); +// Returns a set containing all keys and action_parameters that appear in +// `expr`. Example use case is to extract variables from a constraint to print +// the reason why an entry violates a constraint. +absl::flat_hash_set GetVariables(const ast::Expression& expr); // Cache for results of `Size`. using SizeCache = absl::flat_hash_map; diff --git a/p4_constraints/ast_test.cc b/p4_constraints/ast_test.cc index 5f54ba9..bb575d3 100644 --- a/p4_constraints/ast_test.cc +++ b/p4_constraints/ast_test.cc @@ -294,7 +294,7 @@ TEST(SizeTest, NoCacheOkay) { EXPECT_THAT(Size(expr, nullptr), IsOkAndHolds(Eq(7))); } -TEST(AddMatchFields, ReturnsEmptyForActionParameter) { +TEST(AddVariables, ReturnsEmptyForActionParameter) { Expression expr = ParseRawAst(R"pb( binary_expression { binop: GE @@ -302,7 +302,9 @@ TEST(AddMatchFields, ReturnsEmptyForActionParameter) { right { action_parameter: "2" } } )pb"); - EXPECT_THAT(GetMatchFields(expr), testing::IsEmpty()); + + absl::flat_hash_set expected = {"1", "2"}; + EXPECT_EQ(GetVariables(expr), expected); } } // namespace ast diff --git a/p4_constraints/backend/interpreter.cc b/p4_constraints/backend/interpreter.cc index a603d33..f0e3eaa 100644 --- a/p4_constraints/backend/interpreter.cc +++ b/p4_constraints/backend/interpreter.cc @@ -604,7 +604,7 @@ absl::StatusOr ExplainConstraintViolation( explanation->end_location())); const absl::flat_hash_set relevant_fields = - ast::GetMatchFields(*explanation); + ast::GetVariables(*explanation); return std::visit( gutils::Overload{ [&](const TableEntry& table_entry) -> std::string {