...

Source file src/go.einride.tech/aip/filtering/declarations.go

Documentation: go.einride.tech/aip/filtering

     1  package filtering
     2  
     3  import (
     4  	"fmt"
     5  
     6  	expr "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
     7  	"google.golang.org/protobuf/proto"
     8  	"google.golang.org/protobuf/reflect/protoreflect"
     9  )
    10  
    11  // NewStringConstant creates a new string constant.
    12  func NewStringConstant(value string) *expr.Constant {
    13  	return &expr.Constant{
    14  		ConstantKind: &expr.Constant_StringValue{
    15  			StringValue: value,
    16  		},
    17  	}
    18  }
    19  
    20  // NewFunctionDeclaration creates a new function declaration.
    21  func NewFunctionDeclaration(name string, overloads ...*expr.Decl_FunctionDecl_Overload) *expr.Decl {
    22  	return &expr.Decl{
    23  		Name: name,
    24  		DeclKind: &expr.Decl_Function{
    25  			Function: &expr.Decl_FunctionDecl{
    26  				Overloads: overloads,
    27  			},
    28  		},
    29  	}
    30  }
    31  
    32  // NewFunctionOverload creates a new function overload.
    33  func NewFunctionOverload(id string, result *expr.Type, params ...*expr.Type) *expr.Decl_FunctionDecl_Overload {
    34  	return &expr.Decl_FunctionDecl_Overload{
    35  		OverloadId: id,
    36  		ResultType: result,
    37  		Params:     params,
    38  	}
    39  }
    40  
    41  // NewIdentDeclaration creates a new ident declaration.
    42  func NewIdentDeclaration(name string, identType *expr.Type) *expr.Decl {
    43  	return &expr.Decl{
    44  		Name: name,
    45  		DeclKind: &expr.Decl_Ident{
    46  			Ident: &expr.Decl_IdentDecl{
    47  				Type: identType,
    48  			},
    49  		},
    50  	}
    51  }
    52  
    53  // NewConstantDeclaration creates a new constant ident declaration.
    54  func NewConstantDeclaration(name string, constantType *expr.Type, constantValue *expr.Constant) *expr.Decl {
    55  	return &expr.Decl{
    56  		Name: name,
    57  		DeclKind: &expr.Decl_Ident{
    58  			Ident: &expr.Decl_IdentDecl{
    59  				Type:  constantType,
    60  				Value: constantValue,
    61  			},
    62  		},
    63  	}
    64  }
    65  
    66  // Declarations contain declarations for type-checking filter expressions.
    67  type Declarations struct {
    68  	idents    map[string]*expr.Decl
    69  	functions map[string]*expr.Decl
    70  	enums     map[string]protoreflect.EnumType
    71  }
    72  
    73  // DeclarationOption configures Declarations.
    74  type DeclarationOption func(*Declarations) error
    75  
    76  // DeclareStandardFunction is a DeclarationOption that declares all standard functions and their overloads.
    77  func DeclareStandardFunctions() DeclarationOption {
    78  	return func(declarations *Declarations) error {
    79  		for _, declaration := range StandardFunctionDeclarations() {
    80  			if err := declarations.declare(declaration); err != nil {
    81  				return err
    82  			}
    83  		}
    84  		return nil
    85  	}
    86  }
    87  
    88  // DeclareFunction is a DeclarationOption that declares a single function and its overloads.
    89  func DeclareFunction(name string, overloads ...*expr.Decl_FunctionDecl_Overload) DeclarationOption {
    90  	return func(declarations *Declarations) error {
    91  		return declarations.declareFunction(name, overloads...)
    92  	}
    93  }
    94  
    95  // DeclareIdent is a DeclarationOption that declares a single ident.
    96  func DeclareIdent(name string, t *expr.Type) DeclarationOption {
    97  	return func(declarations *Declarations) error {
    98  		return declarations.declareIdent(name, t)
    99  	}
   100  }
   101  
   102  func DeclareEnumIdent(name string, enumType protoreflect.EnumType) DeclarationOption {
   103  	return func(declarations *Declarations) error {
   104  		return declarations.declareEnumIdent(name, enumType)
   105  	}
   106  }
   107  
   108  // NewDeclarations creates a new set of Declarations for filter expression type-checking.
   109  func NewDeclarations(opts ...DeclarationOption) (*Declarations, error) {
   110  	d := &Declarations{
   111  		idents:    make(map[string]*expr.Decl),
   112  		functions: make(map[string]*expr.Decl),
   113  		enums:     make(map[string]protoreflect.EnumType),
   114  	}
   115  	for _, opt := range opts {
   116  		if err := opt(d); err != nil {
   117  			return nil, err
   118  		}
   119  	}
   120  	return d, nil
   121  }
   122  
   123  func (d *Declarations) LookupIdent(name string) (*expr.Decl, bool) {
   124  	result, ok := d.idents[name]
   125  	return result, ok
   126  }
   127  
   128  func (d *Declarations) LookupFunction(name string) (*expr.Decl, bool) {
   129  	result, ok := d.functions[name]
   130  	return result, ok
   131  }
   132  
   133  func (d *Declarations) LookupEnumIdent(name string) (protoreflect.EnumType, bool) {
   134  	result, ok := d.enums[name]
   135  	return result, ok
   136  }
   137  
   138  func (d *Declarations) declareIdent(name string, t *expr.Type) error {
   139  	if _, ok := d.idents[name]; ok {
   140  		return fmt.Errorf("redeclaration of %s", name)
   141  	}
   142  	d.idents[name] = NewIdentDeclaration(name, t)
   143  	return nil
   144  }
   145  
   146  func (d *Declarations) declareConstant(name string, constantType *expr.Type, constantValue *expr.Constant) error {
   147  	constantDecl := NewConstantDeclaration(name, constantType, constantValue)
   148  	if existingIdent, ok := d.idents[name]; ok {
   149  		if !proto.Equal(constantDecl, existingIdent) {
   150  			return fmt.Errorf("redeclaration of %s", name)
   151  		}
   152  		return nil
   153  	}
   154  	d.idents[name] = constantDecl
   155  	return nil
   156  }
   157  
   158  func (d *Declarations) declareEnumIdent(name string, enumType protoreflect.EnumType) error {
   159  	if _, ok := d.enums[name]; ok {
   160  		return fmt.Errorf("redeclaration of %s", name)
   161  	}
   162  	d.enums[name] = enumType
   163  	enumIdentType := TypeEnum(enumType)
   164  	if err := d.declareIdent(name, enumIdentType); err != nil {
   165  		return err
   166  	}
   167  	for _, fn := range []string{
   168  		FunctionEquals,
   169  		FunctionNotEquals,
   170  	} {
   171  		if err := d.declareFunction(
   172  			fn,
   173  			NewFunctionOverload(fn+"_"+enumIdentType.GetMessageType(), TypeBool, enumIdentType, enumIdentType),
   174  		); err != nil {
   175  			return err
   176  		}
   177  	}
   178  	values := enumType.Descriptor().Values()
   179  	for i := 0; i < values.Len(); i++ {
   180  		valueName := string(values.Get(i).Name())
   181  		if err := d.declareConstant(valueName, enumIdentType, NewStringConstant(valueName)); err != nil {
   182  			return err
   183  		}
   184  	}
   185  	return nil
   186  }
   187  
   188  func (d *Declarations) declareFunction(name string, overloads ...*expr.Decl_FunctionDecl_Overload) error {
   189  	decl, ok := d.functions[name]
   190  	if !ok {
   191  		decl = NewFunctionDeclaration(name)
   192  		d.functions[name] = decl
   193  	}
   194  	function := decl.GetFunction()
   195  NewOverloadLoop:
   196  	for _, newOverload := range overloads {
   197  		for _, existingOverload := range function.GetOverloads() {
   198  			if newOverload.GetOverloadId() == existingOverload.GetOverloadId() {
   199  				if !proto.Equal(newOverload, existingOverload) {
   200  					return fmt.Errorf("redeclaration of overload %s", existingOverload.GetOverloadId())
   201  				}
   202  				continue NewOverloadLoop
   203  			}
   204  		}
   205  		function.Overloads = append(function.Overloads, newOverload)
   206  	}
   207  	return nil
   208  }
   209  
   210  func (d *Declarations) declare(decl *expr.Decl) error {
   211  	switch decl.GetDeclKind().(type) {
   212  	case *expr.Decl_Function:
   213  		return d.declareFunction(decl.GetName(), decl.GetFunction().GetOverloads()...)
   214  	case *expr.Decl_Ident:
   215  		if decl.GetIdent().GetValue() != nil {
   216  			return d.declareConstant(decl.GetName(), decl.GetIdent().GetType(), decl.GetIdent().GetValue())
   217  		}
   218  		return d.declareIdent(decl.GetName(), decl.GetIdent().GetType())
   219  	default:
   220  		return fmt.Errorf("unsupported declaration kind")
   221  	}
   222  }
   223  

View as plain text