From 03bc1a01fcebe9aa3e367586d0ac825cf4a65d04 Mon Sep 17 00:00:00 2001 From: Ivan Pointer Date: Thu, 1 Feb 2024 14:51:29 -0600 Subject: [PATCH] Add filtering declaration options for constant expressions, including booleans. --- filtering/checker_test.go | 86 ++++++++++++++++++++++++++++++++++++++- filtering/declarations.go | 29 ++++++++++++- 2 files changed, 113 insertions(+), 2 deletions(-) diff --git a/filtering/checker_test.go b/filtering/checker_test.go index 756640578d..9b340e5e4c 100644 --- a/filtering/checker_test.go +++ b/filtering/checker_test.go @@ -3,8 +3,10 @@ package filtering import ( "testing" - syntaxv1 "go.einride.tech/aip/proto/gen/einride/example/syntax/v1" + expr "google.golang.org/genproto/googleapis/api/expr/v1alpha1" "gotest.tools/v3/assert" + + syntaxv1 "go.einride.tech/aip/proto/gen/einride/example/syntax/v1" ) func TestChecker(t *testing.T) { @@ -412,6 +414,88 @@ func TestChecker(t *testing.T) { }, }, + { + filter: "IsGreat = true", + declarations: []DeclarationOption{ + DeclareStandardFunctions(), + DeclareIdent("IsGreat", TypeBool), + DeclareConstant("true", TypeBool, &expr.Constant{ConstantKind: &expr.Constant_BoolValue{BoolValue: true}}), + }, + }, + + { + filter: "IsGreat = true", + declarations: []DeclarationOption{ + DeclareStandardFunctions(), + DeclareStandardBoolConstants(), + DeclareIdent("IsGreat", TypeBool), + }, + }, + + { + filter: "IsGreat = True", + declarations: []DeclarationOption{ + DeclareStandardFunctions(), + DeclareStandardBoolConstants(), + DeclareIdent("IsGreat", TypeBool), + }, + }, + + { + filter: "IsGreat = TRUE", + declarations: []DeclarationOption{ + DeclareStandardFunctions(), + DeclareStandardBoolConstants(), + DeclareIdent("IsGreat", TypeBool), + }, + }, + + { + filter: "IsGreat = false", + declarations: []DeclarationOption{ + DeclareStandardFunctions(), + DeclareIdent("IsGreat", TypeBool), + DeclareConstant("false", TypeBool, &expr.Constant{ConstantKind: &expr.Constant_BoolValue{BoolValue: true}}), + }, + }, + + { + filter: "IsGreat = false", + declarations: []DeclarationOption{ + DeclareStandardFunctions(), + DeclareStandardBoolConstants(), + DeclareIdent("IsGreat", TypeBool), + }, + }, + + { + filter: "IsGreat = False", + declarations: []DeclarationOption{ + DeclareStandardFunctions(), + DeclareStandardBoolConstants(), + DeclareIdent("IsGreat", TypeBool), + }, + }, + + { + filter: "IsGreat = FALSE", + declarations: []DeclarationOption{ + DeclareStandardFunctions(), + DeclareStandardBoolConstants(), + DeclareIdent("IsGreat", TypeBool), + }, + }, + + { + filter: "IsGreat = FalsE", + declarations: []DeclarationOption{ + DeclareStandardFunctions(), + DeclareStandardBoolConstants(), + DeclareIdent("IsGreat", TypeBool), + }, + errorContains: "undeclared identifier 'FalsE'", + }, + { filter: "<", errorContains: "unexpected token <", diff --git a/filtering/declarations.go b/filtering/declarations.go index 51a2083968..b5710bb2f3 100644 --- a/filtering/declarations.go +++ b/filtering/declarations.go @@ -73,7 +73,7 @@ type Declarations struct { // DeclarationOption configures Declarations. type DeclarationOption func(*Declarations) error -// DeclareStandardFunction is a DeclarationOption that declares all standard functions and their overloads. +// DeclareStandardFunctions is a DeclarationOption that declares all standard functions and their overloads. func DeclareStandardFunctions() DeclarationOption { return func(declarations *Declarations) error { for _, declaration := range StandardFunctionDeclarations() { @@ -85,6 +85,25 @@ func DeclareStandardFunctions() DeclarationOption { } } +// DeclareStandardBoolConstants is a DeclarationOption that adds a number of variations of "true" and "false" as constant values. +func DeclareStandardBoolConstants() DeclarationOption { + return func(declarations *Declarations) error { + for n, v := range map[string]bool{ + "true": true, + "True": true, + "TRUE": true, + "false": false, + "False": false, + "FALSE": false, + } { + if err := declarations.declareConstant(n, TypeBool, &expr.Constant{ConstantKind: &expr.Constant_BoolValue{BoolValue: v}}); err != nil { + return err + } + } + return nil + } +} + // DeclareFunction is a DeclarationOption that declares a single function and its overloads. func DeclareFunction(name string, overloads ...*expr.Decl_FunctionDecl_Overload) DeclarationOption { return func(declarations *Declarations) error { @@ -99,12 +118,20 @@ func DeclareIdent(name string, t *expr.Type) DeclarationOption { } } +// DeclareEnumIdent is a DeclarationOption that declares an enumeration. func DeclareEnumIdent(name string, enumType protoreflect.EnumType) DeclarationOption { return func(declarations *Declarations) error { return declarations.declareEnumIdent(name, enumType) } } +// DeclareConstant is a DeclarationOption that adds a constant value to the declarations. +func DeclareConstant(name string, constantType *expr.Type, constantValue *expr.Constant) DeclarationOption { + return func(declarations *Declarations) error { + return declarations.declareConstant(name, constantType, constantValue) + } +} + // NewDeclarations creates a new set of Declarations for filter expression type-checking. func NewDeclarations(opts ...DeclarationOption) (*Declarations, error) { d := &Declarations{