mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 18:43:34 +00:00
rebase: bump the golang-dependencies group with 1 update
Bumps the golang-dependencies group with 1 update: [golang.org/x/crypto](https://github.com/golang/crypto). Updates `golang.org/x/crypto` from 0.16.0 to 0.17.0 - [Commits](https://github.com/golang/crypto/compare/v0.16.0...v0.17.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-dependencies ... Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
committed by
mergify[bot]
parent
1ad79314f9
commit
e5d9b68d36
8
vendor/github.com/google/cel-go/interpreter/BUILD.bazel
generated
vendored
8
vendor/github.com/google/cel-go/interpreter/BUILD.bazel
generated
vendored
@ -25,13 +25,14 @@ go_library(
|
||||
importpath = "github.com/google/cel-go/interpreter",
|
||||
deps = [
|
||||
"//common:go_default_library",
|
||||
"//common/ast:go_default_library",
|
||||
"//common/containers:go_default_library",
|
||||
"//common/functions:go_default_library",
|
||||
"//common/operators:go_default_library",
|
||||
"//common/overloads:go_default_library",
|
||||
"//common/types:go_default_library",
|
||||
"//common/types/ref:go_default_library",
|
||||
"//common/types/traits:go_default_library",
|
||||
"//interpreter/functions:go_default_library",
|
||||
"@org_golang_google_genproto_googleapis_api//expr/v1alpha1:go_default_library",
|
||||
"@org_golang_google_protobuf//proto:go_default_library",
|
||||
"@org_golang_google_protobuf//types/known/durationpb:go_default_library",
|
||||
@ -56,12 +57,13 @@ go_test(
|
||||
],
|
||||
deps = [
|
||||
"//checker:go_default_library",
|
||||
"//checker/decls:go_default_library",
|
||||
"//common/containers:go_default_library",
|
||||
"//common/debug:go_default_library",
|
||||
"//common/decls:go_default_library",
|
||||
"//common/functions:go_default_library",
|
||||
"//common/operators:go_default_library",
|
||||
"//common/stdlib:go_default_library",
|
||||
"//common/types:go_default_library",
|
||||
"//interpreter/functions:go_default_library",
|
||||
"//parser:go_default_library",
|
||||
"//test:go_default_library",
|
||||
"//test/proto2pb:go_default_library",
|
||||
|
2
vendor/github.com/google/cel-go/interpreter/activation.go
generated
vendored
2
vendor/github.com/google/cel-go/interpreter/activation.go
generated
vendored
@ -58,7 +58,7 @@ func (emptyActivation) Parent() Activation { return nil }
|
||||
// The output of the lazy binding will overwrite the variable reference in the internal map.
|
||||
//
|
||||
// Values which are not represented as ref.Val types on input may be adapted to a ref.Val using
|
||||
// the ref.TypeAdapter configured in the environment.
|
||||
// the types.Adapter configured in the environment.
|
||||
func NewActivation(bindings any) (Activation, error) {
|
||||
if bindings == nil {
|
||||
return nil, errors.New("bindings must be non-nil")
|
||||
|
42
vendor/github.com/google/cel-go/interpreter/attribute_patterns.go
generated
vendored
42
vendor/github.com/google/cel-go/interpreter/attribute_patterns.go
generated
vendored
@ -15,6 +15,8 @@
|
||||
package interpreter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/google/cel-go/common/containers"
|
||||
"github.com/google/cel-go/common/types"
|
||||
"github.com/google/cel-go/common/types/ref"
|
||||
@ -177,8 +179,8 @@ func numericValueEquals(value any, celValue ref.Val) bool {
|
||||
// NewPartialAttributeFactory returns an AttributeFactory implementation capable of performing
|
||||
// AttributePattern matches with PartialActivation inputs.
|
||||
func NewPartialAttributeFactory(container *containers.Container,
|
||||
adapter ref.TypeAdapter,
|
||||
provider ref.TypeProvider) AttributeFactory {
|
||||
adapter types.Adapter,
|
||||
provider types.Provider) AttributeFactory {
|
||||
fac := NewAttributeFactory(container, adapter, provider)
|
||||
return &partialAttributeFactory{
|
||||
AttributeFactory: fac,
|
||||
@ -191,8 +193,8 @@ func NewPartialAttributeFactory(container *containers.Container,
|
||||
type partialAttributeFactory struct {
|
||||
AttributeFactory
|
||||
container *containers.Container
|
||||
adapter ref.TypeAdapter
|
||||
provider ref.TypeProvider
|
||||
adapter types.Adapter
|
||||
provider types.Provider
|
||||
}
|
||||
|
||||
// AbsoluteAttribute implementation of the AttributeFactory interface which wraps the
|
||||
@ -241,12 +243,15 @@ func (fac *partialAttributeFactory) matchesUnknownPatterns(
|
||||
vars PartialActivation,
|
||||
attrID int64,
|
||||
variableNames []string,
|
||||
qualifiers []Qualifier) (types.Unknown, error) {
|
||||
qualifiers []Qualifier) (*types.Unknown, error) {
|
||||
patterns := vars.UnknownAttributePatterns()
|
||||
candidateIndices := map[int]struct{}{}
|
||||
for _, variable := range variableNames {
|
||||
for i, pat := range patterns {
|
||||
if pat.VariableMatches(variable) {
|
||||
if len(qualifiers) == 0 {
|
||||
return types.NewUnknown(attrID, types.NewAttributeTrail(variable)), nil
|
||||
}
|
||||
candidateIndices[i] = struct{}{}
|
||||
}
|
||||
}
|
||||
@ -255,10 +260,6 @@ func (fac *partialAttributeFactory) matchesUnknownPatterns(
|
||||
if len(candidateIndices) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
// Determine whether to return early if there are no qualifiers.
|
||||
if len(qualifiers) == 0 {
|
||||
return types.Unknown{attrID}, nil
|
||||
}
|
||||
// Resolve the attribute qualifiers into a static set. This prevents more dynamic
|
||||
// Attribute resolutions than necessary when there are multiple unknown patterns
|
||||
// that traverse the same Attribute-based qualifier field.
|
||||
@ -300,7 +301,28 @@ func (fac *partialAttributeFactory) matchesUnknownPatterns(
|
||||
}
|
||||
}
|
||||
if isUnk {
|
||||
return types.Unknown{matchExprID}, nil
|
||||
attr := types.NewAttributeTrail(pat.variable)
|
||||
for i := 0; i < len(qualPats) && i < len(newQuals); i++ {
|
||||
if qual, ok := newQuals[i].(ConstantQualifier); ok {
|
||||
switch v := qual.Value().Value().(type) {
|
||||
case bool:
|
||||
types.QualifyAttribute[bool](attr, v)
|
||||
case float64:
|
||||
types.QualifyAttribute[int64](attr, int64(v))
|
||||
case int64:
|
||||
types.QualifyAttribute[int64](attr, v)
|
||||
case string:
|
||||
types.QualifyAttribute[string](attr, v)
|
||||
case uint64:
|
||||
types.QualifyAttribute[uint64](attr, v)
|
||||
default:
|
||||
types.QualifyAttribute[string](attr, fmt.Sprintf("%v", v))
|
||||
}
|
||||
} else {
|
||||
types.QualifyAttribute[string](attr, "*")
|
||||
}
|
||||
}
|
||||
return types.NewUnknown(matchExprID, attr), nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
|
52
vendor/github.com/google/cel-go/interpreter/attributes.go
generated
vendored
52
vendor/github.com/google/cel-go/interpreter/attributes.go
generated
vendored
@ -22,8 +22,6 @@ import (
|
||||
"github.com/google/cel-go/common/types"
|
||||
"github.com/google/cel-go/common/types/ref"
|
||||
"github.com/google/cel-go/common/types/traits"
|
||||
|
||||
exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
|
||||
)
|
||||
|
||||
// AttributeFactory provides methods creating Attribute and Qualifier values.
|
||||
@ -61,7 +59,7 @@ type AttributeFactory interface {
|
||||
// The qualifier may consider the object type being qualified, if present. If absent, the
|
||||
// qualification should be considered dynamic and the qualification should still work, though
|
||||
// it may be sub-optimal.
|
||||
NewQualifier(objType *exprpb.Type, qualID int64, val any, opt bool) (Qualifier, error)
|
||||
NewQualifier(objType *types.Type, qualID int64, val any, opt bool) (Qualifier, error)
|
||||
}
|
||||
|
||||
// Qualifier marker interface for designating different qualifier values and where they appear
|
||||
@ -131,7 +129,7 @@ type NamespacedAttribute interface {
|
||||
// NewAttributeFactory returns a default AttributeFactory which is produces Attribute values
|
||||
// capable of resolving types by simple names and qualify the values using the supported qualifier
|
||||
// types: bool, int, string, and uint.
|
||||
func NewAttributeFactory(cont *containers.Container, a ref.TypeAdapter, p ref.TypeProvider) AttributeFactory {
|
||||
func NewAttributeFactory(cont *containers.Container, a types.Adapter, p types.Provider) AttributeFactory {
|
||||
return &attrFactory{
|
||||
container: cont,
|
||||
adapter: a,
|
||||
@ -141,8 +139,8 @@ func NewAttributeFactory(cont *containers.Container, a ref.TypeAdapter, p ref.Ty
|
||||
|
||||
type attrFactory struct {
|
||||
container *containers.Container
|
||||
adapter ref.TypeAdapter
|
||||
provider ref.TypeProvider
|
||||
adapter types.Adapter
|
||||
provider types.Provider
|
||||
}
|
||||
|
||||
// AbsoluteAttribute refers to a variable value and an optional qualifier path.
|
||||
@ -199,13 +197,13 @@ func (r *attrFactory) RelativeAttribute(id int64, operand Interpretable) Attribu
|
||||
}
|
||||
|
||||
// NewQualifier is an implementation of the AttributeFactory interface.
|
||||
func (r *attrFactory) NewQualifier(objType *exprpb.Type, qualID int64, val any, opt bool) (Qualifier, error) {
|
||||
func (r *attrFactory) NewQualifier(objType *types.Type, qualID int64, val any, opt bool) (Qualifier, error) {
|
||||
// Before creating a new qualifier check to see if this is a protobuf message field access.
|
||||
// If so, use the precomputed GetFrom qualification method rather than the standard
|
||||
// stringQualifier.
|
||||
str, isStr := val.(string)
|
||||
if isStr && objType != nil && objType.GetMessageType() != "" {
|
||||
ft, found := r.provider.FindFieldType(objType.GetMessageType(), str)
|
||||
if isStr && objType != nil && objType.Kind() == types.StructKind {
|
||||
ft, found := r.provider.FindStructFieldType(objType.TypeName(), str)
|
||||
if found && ft.IsSet != nil && ft.GetFrom != nil {
|
||||
return &fieldQualifier{
|
||||
id: qualID,
|
||||
@ -225,8 +223,8 @@ type absoluteAttribute struct {
|
||||
// (package) of the expression.
|
||||
namespaceNames []string
|
||||
qualifiers []Qualifier
|
||||
adapter ref.TypeAdapter
|
||||
provider ref.TypeProvider
|
||||
adapter types.Adapter
|
||||
provider types.Provider
|
||||
fac AttributeFactory
|
||||
}
|
||||
|
||||
@ -325,7 +323,7 @@ type conditionalAttribute struct {
|
||||
expr Interpretable
|
||||
truthy Attribute
|
||||
falsy Attribute
|
||||
adapter ref.TypeAdapter
|
||||
adapter types.Adapter
|
||||
fac AttributeFactory
|
||||
}
|
||||
|
||||
@ -393,8 +391,8 @@ func (a *conditionalAttribute) String() string {
|
||||
type maybeAttribute struct {
|
||||
id int64
|
||||
attrs []NamespacedAttribute
|
||||
adapter ref.TypeAdapter
|
||||
provider ref.TypeProvider
|
||||
adapter types.Adapter
|
||||
provider types.Provider
|
||||
fac AttributeFactory
|
||||
}
|
||||
|
||||
@ -511,7 +509,7 @@ type relativeAttribute struct {
|
||||
id int64
|
||||
operand Interpretable
|
||||
qualifiers []Qualifier
|
||||
adapter ref.TypeAdapter
|
||||
adapter types.Adapter
|
||||
fac AttributeFactory
|
||||
}
|
||||
|
||||
@ -576,7 +574,7 @@ func (a *relativeAttribute) String() string {
|
||||
return fmt.Sprintf("id: %v, operand: %v", a.id, a.operand)
|
||||
}
|
||||
|
||||
func newQualifier(adapter ref.TypeAdapter, id int64, v any, opt bool) (Qualifier, error) {
|
||||
func newQualifier(adapter types.Adapter, id int64, v any, opt bool) (Qualifier, error) {
|
||||
var qual Qualifier
|
||||
switch val := v.(type) {
|
||||
case Attribute:
|
||||
@ -657,7 +655,7 @@ func newQualifier(adapter ref.TypeAdapter, id int64, v any, opt bool) (Qualifier
|
||||
qual = &doubleQualifier{
|
||||
id: id, value: float64(val), celValue: val, adapter: adapter, optional: opt,
|
||||
}
|
||||
case types.Unknown:
|
||||
case *types.Unknown:
|
||||
qual = &unknownQualifier{id: id, value: val}
|
||||
default:
|
||||
if q, ok := v.(Qualifier); ok {
|
||||
@ -689,7 +687,7 @@ type stringQualifier struct {
|
||||
id int64
|
||||
value string
|
||||
celValue ref.Val
|
||||
adapter ref.TypeAdapter
|
||||
adapter types.Adapter
|
||||
optional bool
|
||||
}
|
||||
|
||||
@ -790,7 +788,7 @@ type intQualifier struct {
|
||||
id int64
|
||||
value int64
|
||||
celValue ref.Val
|
||||
adapter ref.TypeAdapter
|
||||
adapter types.Adapter
|
||||
optional bool
|
||||
}
|
||||
|
||||
@ -917,7 +915,7 @@ type uintQualifier struct {
|
||||
id int64
|
||||
value uint64
|
||||
celValue ref.Val
|
||||
adapter ref.TypeAdapter
|
||||
adapter types.Adapter
|
||||
optional bool
|
||||
}
|
||||
|
||||
@ -982,7 +980,7 @@ type boolQualifier struct {
|
||||
id int64
|
||||
value bool
|
||||
celValue ref.Val
|
||||
adapter ref.TypeAdapter
|
||||
adapter types.Adapter
|
||||
optional bool
|
||||
}
|
||||
|
||||
@ -1035,8 +1033,8 @@ func (q *boolQualifier) Value() ref.Val {
|
||||
type fieldQualifier struct {
|
||||
id int64
|
||||
Name string
|
||||
FieldType *ref.FieldType
|
||||
adapter ref.TypeAdapter
|
||||
FieldType *types.FieldType
|
||||
adapter types.Adapter
|
||||
optional bool
|
||||
}
|
||||
|
||||
@ -1094,7 +1092,7 @@ type doubleQualifier struct {
|
||||
id int64
|
||||
value float64
|
||||
celValue ref.Val
|
||||
adapter ref.TypeAdapter
|
||||
adapter types.Adapter
|
||||
optional bool
|
||||
}
|
||||
|
||||
@ -1131,7 +1129,7 @@ func (q *doubleQualifier) Value() ref.Val {
|
||||
// for any value subject to qualification. This is consistent with CEL's unknown handling elsewhere.
|
||||
type unknownQualifier struct {
|
||||
id int64
|
||||
value types.Unknown
|
||||
value *types.Unknown
|
||||
}
|
||||
|
||||
// ID is an implementation of the Qualifier interface method.
|
||||
@ -1225,10 +1223,10 @@ func attrQualifyIfPresent(fac AttributeFactory, vars Activation, obj any, qualAt
|
||||
|
||||
// refQualify attempts to convert the value to a CEL value and then uses reflection methods to try and
|
||||
// apply the qualifier with the option to presence test field accesses before retrieving field values.
|
||||
func refQualify(adapter ref.TypeAdapter, obj any, idx ref.Val, presenceTest, presenceOnly bool) (ref.Val, bool, error) {
|
||||
func refQualify(adapter types.Adapter, obj any, idx ref.Val, presenceTest, presenceOnly bool) (ref.Val, bool, error) {
|
||||
celVal := adapter.NativeToValue(obj)
|
||||
switch v := celVal.(type) {
|
||||
case types.Unknown:
|
||||
case *types.Unknown:
|
||||
return v, true, nil
|
||||
case *types.Err:
|
||||
return nil, false, v
|
||||
|
10
vendor/github.com/google/cel-go/interpreter/decorators.go
generated
vendored
10
vendor/github.com/google/cel-go/interpreter/decorators.go
generated
vendored
@ -75,15 +75,13 @@ func decDisableShortcircuits() InterpretableDecorator {
|
||||
switch expr := i.(type) {
|
||||
case *evalOr:
|
||||
return &evalExhaustiveOr{
|
||||
id: expr.id,
|
||||
lhs: expr.lhs,
|
||||
rhs: expr.rhs,
|
||||
id: expr.id,
|
||||
terms: expr.terms,
|
||||
}, nil
|
||||
case *evalAnd:
|
||||
return &evalExhaustiveAnd{
|
||||
id: expr.id,
|
||||
lhs: expr.lhs,
|
||||
rhs: expr.rhs,
|
||||
id: expr.id,
|
||||
terms: expr.terms,
|
||||
}, nil
|
||||
case *evalFold:
|
||||
expr.exhaustive = true
|
||||
|
2
vendor/github.com/google/cel-go/interpreter/dispatcher.go
generated
vendored
2
vendor/github.com/google/cel-go/interpreter/dispatcher.go
generated
vendored
@ -17,7 +17,7 @@ package interpreter
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/google/cel-go/interpreter/functions"
|
||||
"github.com/google/cel-go/common/functions"
|
||||
)
|
||||
|
||||
// Dispatcher resolves function calls to their appropriate overload.
|
||||
|
6
vendor/github.com/google/cel-go/interpreter/evalstate.go
generated
vendored
6
vendor/github.com/google/cel-go/interpreter/evalstate.go
generated
vendored
@ -66,7 +66,11 @@ func (s *evalState) Value(exprID int64) (ref.Val, bool) {
|
||||
|
||||
// SetValue is an implementation of the EvalState interface method.
|
||||
func (s *evalState) SetValue(exprID int64, val ref.Val) {
|
||||
s.values[exprID] = val
|
||||
if val == nil {
|
||||
delete(s.values, exprID)
|
||||
} else {
|
||||
s.values[exprID] = val
|
||||
}
|
||||
}
|
||||
|
||||
// Reset implements the EvalState interface method.
|
||||
|
2
vendor/github.com/google/cel-go/interpreter/formatting.go
generated
vendored
2
vendor/github.com/google/cel-go/interpreter/formatting.go
generated
vendored
@ -25,7 +25,7 @@ import (
|
||||
"github.com/google/cel-go/common/types/ref"
|
||||
)
|
||||
|
||||
type typeVerifier func(int64, ...*types.TypeValue) (bool, error)
|
||||
type typeVerifier func(int64, ...ref.Type) (bool, error)
|
||||
|
||||
// InterpolateFormattedString checks the syntax and cardinality of any string.format calls present in the expression and reports
|
||||
// any errors at compile time.
|
||||
|
9
vendor/github.com/google/cel-go/interpreter/functions/BUILD.bazel
generated
vendored
9
vendor/github.com/google/cel-go/interpreter/functions/BUILD.bazel
generated
vendored
@ -7,16 +7,11 @@ package(
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
srcs = [
|
||||
"functions.go",
|
||||
"standard.go",
|
||||
],
|
||||
importpath = "github.com/google/cel-go/interpreter/functions",
|
||||
deps = [
|
||||
"//common/operators:go_default_library",
|
||||
"//common/overloads:go_default_library",
|
||||
"//common/types:go_default_library",
|
||||
"//common/types/ref:go_default_library",
|
||||
"//common/types/traits:go_default_library",
|
||||
"//common/functions:go_default_library",
|
||||
],
|
||||
)
|
||||
|
33
vendor/github.com/google/cel-go/interpreter/functions/functions.go
generated
vendored
33
vendor/github.com/google/cel-go/interpreter/functions/functions.go
generated
vendored
@ -16,7 +16,7 @@
|
||||
// interpreter and as declared within the checker#StandardDeclarations.
|
||||
package functions
|
||||
|
||||
import "github.com/google/cel-go/common/types/ref"
|
||||
import fn "github.com/google/cel-go/common/functions"
|
||||
|
||||
// Overload defines a named overload of a function, indicating an operand trait
|
||||
// which must be present on the first argument to the overload as well as one
|
||||
@ -26,37 +26,14 @@ import "github.com/google/cel-go/common/types/ref"
|
||||
// and the specializations simplify the call contract for implementers of
|
||||
// types with operator overloads. Any added complexity is assumed to be handled
|
||||
// by the generic FunctionOp.
|
||||
type Overload struct {
|
||||
// Operator name as written in an expression or defined within
|
||||
// operators.go.
|
||||
Operator string
|
||||
|
||||
// Operand trait used to dispatch the call. The zero-value indicates a
|
||||
// global function overload or that one of the Unary / Binary / Function
|
||||
// definitions should be used to execute the call.
|
||||
OperandTrait int
|
||||
|
||||
// Unary defines the overload with a UnaryOp implementation. May be nil.
|
||||
Unary UnaryOp
|
||||
|
||||
// Binary defines the overload with a BinaryOp implementation. May be nil.
|
||||
Binary BinaryOp
|
||||
|
||||
// Function defines the overload with a FunctionOp implementation. May be
|
||||
// nil.
|
||||
Function FunctionOp
|
||||
|
||||
// NonStrict specifies whether the Overload will tolerate arguments that
|
||||
// are types.Err or types.Unknown.
|
||||
NonStrict bool
|
||||
}
|
||||
type Overload = fn.Overload
|
||||
|
||||
// UnaryOp is a function that takes a single value and produces an output.
|
||||
type UnaryOp func(value ref.Val) ref.Val
|
||||
type UnaryOp = fn.UnaryOp
|
||||
|
||||
// BinaryOp is a function that takes two values and produces an output.
|
||||
type BinaryOp func(lhs ref.Val, rhs ref.Val) ref.Val
|
||||
type BinaryOp = fn.BinaryOp
|
||||
|
||||
// FunctionOp is a function with accepts zero or more arguments and produces
|
||||
// a value or error as a result.
|
||||
type FunctionOp func(values ...ref.Val) ref.Val
|
||||
type FunctionOp = fn.FunctionOp
|
||||
|
270
vendor/github.com/google/cel-go/interpreter/functions/standard.go
generated
vendored
270
vendor/github.com/google/cel-go/interpreter/functions/standard.go
generated
vendored
@ -1,270 +0,0 @@
|
||||
// Copyright 2018 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package functions
|
||||
|
||||
import (
|
||||
"github.com/google/cel-go/common/operators"
|
||||
"github.com/google/cel-go/common/overloads"
|
||||
"github.com/google/cel-go/common/types"
|
||||
"github.com/google/cel-go/common/types/ref"
|
||||
"github.com/google/cel-go/common/types/traits"
|
||||
)
|
||||
|
||||
// StandardOverloads returns the definitions of the built-in overloads.
|
||||
func StandardOverloads() []*Overload {
|
||||
return []*Overload{
|
||||
// Logical not (!a)
|
||||
{
|
||||
Operator: operators.LogicalNot,
|
||||
OperandTrait: traits.NegatorType,
|
||||
Unary: func(value ref.Val) ref.Val {
|
||||
if !types.IsBool(value) {
|
||||
return types.ValOrErr(value, "no such overload")
|
||||
}
|
||||
return value.(traits.Negater).Negate()
|
||||
}},
|
||||
// Not strictly false: IsBool(a) ? a : true
|
||||
{
|
||||
Operator: operators.NotStrictlyFalse,
|
||||
Unary: notStrictlyFalse},
|
||||
// Deprecated: not strictly false, may be overridden in the environment.
|
||||
{
|
||||
Operator: operators.OldNotStrictlyFalse,
|
||||
Unary: notStrictlyFalse},
|
||||
|
||||
// Less than operator
|
||||
{Operator: operators.Less,
|
||||
OperandTrait: traits.ComparerType,
|
||||
Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
|
||||
cmp := lhs.(traits.Comparer).Compare(rhs)
|
||||
if cmp == types.IntNegOne {
|
||||
return types.True
|
||||
}
|
||||
if cmp == types.IntOne || cmp == types.IntZero {
|
||||
return types.False
|
||||
}
|
||||
return cmp
|
||||
}},
|
||||
|
||||
// Less than or equal operator
|
||||
{Operator: operators.LessEquals,
|
||||
OperandTrait: traits.ComparerType,
|
||||
Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
|
||||
cmp := lhs.(traits.Comparer).Compare(rhs)
|
||||
if cmp == types.IntNegOne || cmp == types.IntZero {
|
||||
return types.True
|
||||
}
|
||||
if cmp == types.IntOne {
|
||||
return types.False
|
||||
}
|
||||
return cmp
|
||||
}},
|
||||
|
||||
// Greater than operator
|
||||
{Operator: operators.Greater,
|
||||
OperandTrait: traits.ComparerType,
|
||||
Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
|
||||
cmp := lhs.(traits.Comparer).Compare(rhs)
|
||||
if cmp == types.IntOne {
|
||||
return types.True
|
||||
}
|
||||
if cmp == types.IntNegOne || cmp == types.IntZero {
|
||||
return types.False
|
||||
}
|
||||
return cmp
|
||||
}},
|
||||
|
||||
// Greater than equal operators
|
||||
{Operator: operators.GreaterEquals,
|
||||
OperandTrait: traits.ComparerType,
|
||||
Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
|
||||
cmp := lhs.(traits.Comparer).Compare(rhs)
|
||||
if cmp == types.IntOne || cmp == types.IntZero {
|
||||
return types.True
|
||||
}
|
||||
if cmp == types.IntNegOne {
|
||||
return types.False
|
||||
}
|
||||
return cmp
|
||||
}},
|
||||
|
||||
// Add operator
|
||||
{Operator: operators.Add,
|
||||
OperandTrait: traits.AdderType,
|
||||
Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
|
||||
return lhs.(traits.Adder).Add(rhs)
|
||||
}},
|
||||
|
||||
// Subtract operators
|
||||
{Operator: operators.Subtract,
|
||||
OperandTrait: traits.SubtractorType,
|
||||
Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
|
||||
return lhs.(traits.Subtractor).Subtract(rhs)
|
||||
}},
|
||||
|
||||
// Multiply operator
|
||||
{Operator: operators.Multiply,
|
||||
OperandTrait: traits.MultiplierType,
|
||||
Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
|
||||
return lhs.(traits.Multiplier).Multiply(rhs)
|
||||
}},
|
||||
|
||||
// Divide operator
|
||||
{Operator: operators.Divide,
|
||||
OperandTrait: traits.DividerType,
|
||||
Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
|
||||
return lhs.(traits.Divider).Divide(rhs)
|
||||
}},
|
||||
|
||||
// Modulo operator
|
||||
{Operator: operators.Modulo,
|
||||
OperandTrait: traits.ModderType,
|
||||
Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
|
||||
return lhs.(traits.Modder).Modulo(rhs)
|
||||
}},
|
||||
|
||||
// Negate operator
|
||||
{Operator: operators.Negate,
|
||||
OperandTrait: traits.NegatorType,
|
||||
Unary: func(value ref.Val) ref.Val {
|
||||
if types.IsBool(value) {
|
||||
return types.ValOrErr(value, "no such overload")
|
||||
}
|
||||
return value.(traits.Negater).Negate()
|
||||
}},
|
||||
|
||||
// Index operator
|
||||
{Operator: operators.Index,
|
||||
OperandTrait: traits.IndexerType,
|
||||
Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
|
||||
return lhs.(traits.Indexer).Get(rhs)
|
||||
}},
|
||||
|
||||
// Size function
|
||||
{Operator: overloads.Size,
|
||||
OperandTrait: traits.SizerType,
|
||||
Unary: func(value ref.Val) ref.Val {
|
||||
return value.(traits.Sizer).Size()
|
||||
}},
|
||||
|
||||
// In operator
|
||||
{Operator: operators.In, Binary: inAggregate},
|
||||
// Deprecated: in operator, may be overridden in the environment.
|
||||
{Operator: operators.OldIn, Binary: inAggregate},
|
||||
|
||||
// Matches function
|
||||
{Operator: overloads.Matches,
|
||||
OperandTrait: traits.MatcherType,
|
||||
Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
|
||||
return lhs.(traits.Matcher).Match(rhs)
|
||||
}},
|
||||
|
||||
// Type conversion functions
|
||||
// TODO: verify type conversion safety of numeric values.
|
||||
|
||||
// Int conversions.
|
||||
{Operator: overloads.TypeConvertInt,
|
||||
Unary: func(value ref.Val) ref.Val {
|
||||
return value.ConvertToType(types.IntType)
|
||||
}},
|
||||
|
||||
// Uint conversions.
|
||||
{Operator: overloads.TypeConvertUint,
|
||||
Unary: func(value ref.Val) ref.Val {
|
||||
return value.ConvertToType(types.UintType)
|
||||
}},
|
||||
|
||||
// Double conversions.
|
||||
{Operator: overloads.TypeConvertDouble,
|
||||
Unary: func(value ref.Val) ref.Val {
|
||||
return value.ConvertToType(types.DoubleType)
|
||||
}},
|
||||
|
||||
// Bool conversions.
|
||||
{Operator: overloads.TypeConvertBool,
|
||||
Unary: func(value ref.Val) ref.Val {
|
||||
return value.ConvertToType(types.BoolType)
|
||||
}},
|
||||
|
||||
// Bytes conversions.
|
||||
{Operator: overloads.TypeConvertBytes,
|
||||
Unary: func(value ref.Val) ref.Val {
|
||||
return value.ConvertToType(types.BytesType)
|
||||
}},
|
||||
|
||||
// String conversions.
|
||||
{Operator: overloads.TypeConvertString,
|
||||
Unary: func(value ref.Val) ref.Val {
|
||||
return value.ConvertToType(types.StringType)
|
||||
}},
|
||||
|
||||
// Timestamp conversions.
|
||||
{Operator: overloads.TypeConvertTimestamp,
|
||||
Unary: func(value ref.Val) ref.Val {
|
||||
return value.ConvertToType(types.TimestampType)
|
||||
}},
|
||||
|
||||
// Duration conversions.
|
||||
{Operator: overloads.TypeConvertDuration,
|
||||
Unary: func(value ref.Val) ref.Val {
|
||||
return value.ConvertToType(types.DurationType)
|
||||
}},
|
||||
|
||||
// Type operations.
|
||||
{Operator: overloads.TypeConvertType,
|
||||
Unary: func(value ref.Val) ref.Val {
|
||||
return value.ConvertToType(types.TypeType)
|
||||
}},
|
||||
|
||||
// Dyn conversion (identity function).
|
||||
{Operator: overloads.TypeConvertDyn,
|
||||
Unary: func(value ref.Val) ref.Val {
|
||||
return value
|
||||
}},
|
||||
|
||||
{Operator: overloads.Iterator,
|
||||
OperandTrait: traits.IterableType,
|
||||
Unary: func(value ref.Val) ref.Val {
|
||||
return value.(traits.Iterable).Iterator()
|
||||
}},
|
||||
|
||||
{Operator: overloads.HasNext,
|
||||
OperandTrait: traits.IteratorType,
|
||||
Unary: func(value ref.Val) ref.Val {
|
||||
return value.(traits.Iterator).HasNext()
|
||||
}},
|
||||
|
||||
{Operator: overloads.Next,
|
||||
OperandTrait: traits.IteratorType,
|
||||
Unary: func(value ref.Val) ref.Val {
|
||||
return value.(traits.Iterator).Next()
|
||||
}},
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func notStrictlyFalse(value ref.Val) ref.Val {
|
||||
if types.IsBool(value) {
|
||||
return value
|
||||
}
|
||||
return types.True
|
||||
}
|
||||
|
||||
func inAggregate(lhs ref.Val, rhs ref.Val) ref.Val {
|
||||
if rhs.Type().HasTrait(traits.ContainerType) {
|
||||
return rhs.(traits.Container).Contains(lhs)
|
||||
}
|
||||
return types.ValOrErr(rhs, "no such overload")
|
||||
}
|
317
vendor/github.com/google/cel-go/interpreter/interpretable.go
generated
vendored
317
vendor/github.com/google/cel-go/interpreter/interpretable.go
generated
vendored
@ -17,12 +17,12 @@ package interpreter
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/google/cel-go/common/functions"
|
||||
"github.com/google/cel-go/common/operators"
|
||||
"github.com/google/cel-go/common/overloads"
|
||||
"github.com/google/cel-go/common/types"
|
||||
"github.com/google/cel-go/common/types/ref"
|
||||
"github.com/google/cel-go/common/types/traits"
|
||||
"github.com/google/cel-go/interpreter/functions"
|
||||
)
|
||||
|
||||
// Interpretable can accept a given Activation and produce a value along with
|
||||
@ -52,7 +52,7 @@ type InterpretableAttribute interface {
|
||||
Attr() Attribute
|
||||
|
||||
// Adapter returns the type adapter to be used for adapting resolved Attribute values.
|
||||
Adapter() ref.TypeAdapter
|
||||
Adapter() types.Adapter
|
||||
|
||||
// AddQualifier proxies the Attribute.AddQualifier method.
|
||||
//
|
||||
@ -202,9 +202,8 @@ func (cons *evalConst) Value() ref.Val {
|
||||
}
|
||||
|
||||
type evalOr struct {
|
||||
id int64
|
||||
lhs Interpretable
|
||||
rhs Interpretable
|
||||
id int64
|
||||
terms []Interpretable
|
||||
}
|
||||
|
||||
// ID implements the Interpretable interface method.
|
||||
@ -214,41 +213,39 @@ func (or *evalOr) ID() int64 {
|
||||
|
||||
// Eval implements the Interpretable interface method.
|
||||
func (or *evalOr) Eval(ctx Activation) ref.Val {
|
||||
// short-circuit lhs.
|
||||
lVal := or.lhs.Eval(ctx)
|
||||
lBool, lok := lVal.(types.Bool)
|
||||
if lok && lBool == types.True {
|
||||
return types.True
|
||||
var err ref.Val = nil
|
||||
var unk *types.Unknown
|
||||
for _, term := range or.terms {
|
||||
val := term.Eval(ctx)
|
||||
boolVal, ok := val.(types.Bool)
|
||||
// short-circuit on true.
|
||||
if ok && boolVal == types.True {
|
||||
return types.True
|
||||
}
|
||||
if !ok {
|
||||
isUnk := false
|
||||
unk, isUnk = types.MaybeMergeUnknowns(val, unk)
|
||||
if !isUnk && err == nil {
|
||||
if types.IsError(val) {
|
||||
err = val
|
||||
} else {
|
||||
err = types.MaybeNoSuchOverloadErr(val)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// short-circuit on rhs.
|
||||
rVal := or.rhs.Eval(ctx)
|
||||
rBool, rok := rVal.(types.Bool)
|
||||
if rok && rBool == types.True {
|
||||
return types.True
|
||||
if unk != nil {
|
||||
return unk
|
||||
}
|
||||
// return if both sides are bool false.
|
||||
if lok && rok {
|
||||
return types.False
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO: return both values as a set if both are unknown or error.
|
||||
// prefer left unknown to right unknown.
|
||||
if types.IsUnknown(lVal) {
|
||||
return lVal
|
||||
}
|
||||
if types.IsUnknown(rVal) {
|
||||
return rVal
|
||||
}
|
||||
// If the left-hand side is non-boolean return it as the error.
|
||||
if types.IsError(lVal) {
|
||||
return lVal
|
||||
}
|
||||
return types.ValOrErr(rVal, "no such overload")
|
||||
return types.False
|
||||
}
|
||||
|
||||
type evalAnd struct {
|
||||
id int64
|
||||
lhs Interpretable
|
||||
rhs Interpretable
|
||||
id int64
|
||||
terms []Interpretable
|
||||
}
|
||||
|
||||
// ID implements the Interpretable interface method.
|
||||
@ -258,35 +255,34 @@ func (and *evalAnd) ID() int64 {
|
||||
|
||||
// Eval implements the Interpretable interface method.
|
||||
func (and *evalAnd) Eval(ctx Activation) ref.Val {
|
||||
// short-circuit lhs.
|
||||
lVal := and.lhs.Eval(ctx)
|
||||
lBool, lok := lVal.(types.Bool)
|
||||
if lok && lBool == types.False {
|
||||
return types.False
|
||||
var err ref.Val = nil
|
||||
var unk *types.Unknown
|
||||
for _, term := range and.terms {
|
||||
val := term.Eval(ctx)
|
||||
boolVal, ok := val.(types.Bool)
|
||||
// short-circuit on false.
|
||||
if ok && boolVal == types.False {
|
||||
return types.False
|
||||
}
|
||||
if !ok {
|
||||
isUnk := false
|
||||
unk, isUnk = types.MaybeMergeUnknowns(val, unk)
|
||||
if !isUnk && err == nil {
|
||||
if types.IsError(val) {
|
||||
err = val
|
||||
} else {
|
||||
err = types.MaybeNoSuchOverloadErr(val)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// short-circuit on rhs.
|
||||
rVal := and.rhs.Eval(ctx)
|
||||
rBool, rok := rVal.(types.Bool)
|
||||
if rok && rBool == types.False {
|
||||
return types.False
|
||||
if unk != nil {
|
||||
return unk
|
||||
}
|
||||
// return if both sides are bool true.
|
||||
if lok && rok {
|
||||
return types.True
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO: return both values as a set if both are unknown or error.
|
||||
// prefer left unknown to right unknown.
|
||||
if types.IsUnknown(lVal) {
|
||||
return lVal
|
||||
}
|
||||
if types.IsUnknown(rVal) {
|
||||
return rVal
|
||||
}
|
||||
// If the left-hand side is non-boolean return it as the error.
|
||||
if types.IsError(lVal) {
|
||||
return lVal
|
||||
}
|
||||
return types.ValOrErr(rVal, "no such overload")
|
||||
return types.True
|
||||
}
|
||||
|
||||
type evalEq struct {
|
||||
@ -579,7 +575,7 @@ type evalList struct {
|
||||
elems []Interpretable
|
||||
optionals []bool
|
||||
hasOptionals bool
|
||||
adapter ref.TypeAdapter
|
||||
adapter types.Adapter
|
||||
}
|
||||
|
||||
// ID implements the Interpretable interface method.
|
||||
@ -625,7 +621,7 @@ type evalMap struct {
|
||||
vals []Interpretable
|
||||
optionals []bool
|
||||
hasOptionals bool
|
||||
adapter ref.TypeAdapter
|
||||
adapter types.Adapter
|
||||
}
|
||||
|
||||
// ID implements the Interpretable interface method.
|
||||
@ -689,7 +685,7 @@ type evalObj struct {
|
||||
vals []Interpretable
|
||||
optionals []bool
|
||||
hasOptionals bool
|
||||
provider ref.TypeProvider
|
||||
provider types.Provider
|
||||
}
|
||||
|
||||
// ID implements the Interpretable interface method.
|
||||
@ -739,7 +735,7 @@ type evalFold struct {
|
||||
cond Interpretable
|
||||
step Interpretable
|
||||
result Interpretable
|
||||
adapter ref.TypeAdapter
|
||||
adapter types.Adapter
|
||||
exhaustive bool
|
||||
interruptable bool
|
||||
}
|
||||
@ -865,18 +861,40 @@ type evalWatchAttr struct {
|
||||
// AddQualifier creates a wrapper over the incoming qualifier which observes the qualification
|
||||
// result.
|
||||
func (e *evalWatchAttr) AddQualifier(q Qualifier) (Attribute, error) {
|
||||
cq, isConst := q.(ConstantQualifier)
|
||||
if isConst {
|
||||
switch qual := q.(type) {
|
||||
// By default, the qualifier is either a constant or an attribute
|
||||
// There may be some custom cases where the attribute is neither.
|
||||
case ConstantQualifier:
|
||||
// Expose a method to test whether the qualifier matches the input pattern.
|
||||
q = &evalWatchConstQual{
|
||||
ConstantQualifier: cq,
|
||||
ConstantQualifier: qual,
|
||||
observer: e.observer,
|
||||
adapter: e.InterpretableAttribute.Adapter(),
|
||||
adapter: e.Adapter(),
|
||||
}
|
||||
} else {
|
||||
q = &evalWatchQual{
|
||||
Qualifier: q,
|
||||
case *evalWatchAttr:
|
||||
// Unwrap the evalWatchAttr since the observation will be applied during Qualify or
|
||||
// QualifyIfPresent rather than Eval.
|
||||
q = &evalWatchAttrQual{
|
||||
Attribute: qual.InterpretableAttribute,
|
||||
observer: e.observer,
|
||||
adapter: e.InterpretableAttribute.Adapter(),
|
||||
adapter: e.Adapter(),
|
||||
}
|
||||
case Attribute:
|
||||
// Expose methods which intercept the qualification prior to being applied as a qualifier.
|
||||
// Using this interface ensures that the qualifier is converted to a constant value one
|
||||
// time during attribute pattern matching as the method embeds the Attribute interface
|
||||
// needed to trip the conversion to a constant.
|
||||
q = &evalWatchAttrQual{
|
||||
Attribute: qual,
|
||||
observer: e.observer,
|
||||
adapter: e.Adapter(),
|
||||
}
|
||||
default:
|
||||
// This is likely a custom qualifier type.
|
||||
q = &evalWatchQual{
|
||||
Qualifier: qual,
|
||||
observer: e.observer,
|
||||
adapter: e.Adapter(),
|
||||
}
|
||||
}
|
||||
_, err := e.InterpretableAttribute.AddQualifier(q)
|
||||
@ -895,7 +913,7 @@ func (e *evalWatchAttr) Eval(vars Activation) ref.Val {
|
||||
type evalWatchConstQual struct {
|
||||
ConstantQualifier
|
||||
observer EvalObserver
|
||||
adapter ref.TypeAdapter
|
||||
adapter types.Adapter
|
||||
}
|
||||
|
||||
// Qualify observes the qualification of a object via a constant boolean, int, string, or uint.
|
||||
@ -934,11 +952,48 @@ func (e *evalWatchConstQual) QualifierValueEquals(value any) bool {
|
||||
return ok && qve.QualifierValueEquals(value)
|
||||
}
|
||||
|
||||
// evalWatchAttrQual observes the qualification of an object by a value computed at runtime.
|
||||
type evalWatchAttrQual struct {
|
||||
Attribute
|
||||
observer EvalObserver
|
||||
adapter ref.TypeAdapter
|
||||
}
|
||||
|
||||
// Qualify observes the qualification of a object via a value computed at runtime.
|
||||
func (e *evalWatchAttrQual) Qualify(vars Activation, obj any) (any, error) {
|
||||
out, err := e.Attribute.Qualify(vars, obj)
|
||||
var val ref.Val
|
||||
if err != nil {
|
||||
val = types.WrapErr(err)
|
||||
} else {
|
||||
val = e.adapter.NativeToValue(out)
|
||||
}
|
||||
e.observer(e.ID(), e.Attribute, val)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// QualifyIfPresent conditionally qualifies the variable and only records a value if one is present.
|
||||
func (e *evalWatchAttrQual) QualifyIfPresent(vars Activation, obj any, presenceOnly bool) (any, bool, error) {
|
||||
out, present, err := e.Attribute.QualifyIfPresent(vars, obj, presenceOnly)
|
||||
var val ref.Val
|
||||
if err != nil {
|
||||
val = types.WrapErr(err)
|
||||
} else if out != nil {
|
||||
val = e.adapter.NativeToValue(out)
|
||||
} else if presenceOnly {
|
||||
val = types.Bool(present)
|
||||
}
|
||||
if present || presenceOnly {
|
||||
e.observer(e.ID(), e.Attribute, val)
|
||||
}
|
||||
return out, present, err
|
||||
}
|
||||
|
||||
// evalWatchQual observes the qualification of an object by a value computed at runtime.
|
||||
type evalWatchQual struct {
|
||||
Qualifier
|
||||
observer EvalObserver
|
||||
adapter ref.TypeAdapter
|
||||
adapter types.Adapter
|
||||
}
|
||||
|
||||
// Qualify observes the qualification of a object via a value computed at runtime.
|
||||
@ -986,9 +1041,8 @@ func (e *evalWatchConst) Eval(vars Activation) ref.Val {
|
||||
|
||||
// evalExhaustiveOr is just like evalOr, but does not short-circuit argument evaluation.
|
||||
type evalExhaustiveOr struct {
|
||||
id int64
|
||||
lhs Interpretable
|
||||
rhs Interpretable
|
||||
id int64
|
||||
terms []Interpretable
|
||||
}
|
||||
|
||||
// ID implements the Interpretable interface method.
|
||||
@ -998,38 +1052,44 @@ func (or *evalExhaustiveOr) ID() int64 {
|
||||
|
||||
// Eval implements the Interpretable interface method.
|
||||
func (or *evalExhaustiveOr) Eval(ctx Activation) ref.Val {
|
||||
lVal := or.lhs.Eval(ctx)
|
||||
rVal := or.rhs.Eval(ctx)
|
||||
lBool, lok := lVal.(types.Bool)
|
||||
if lok && lBool == types.True {
|
||||
var err ref.Val = nil
|
||||
var unk *types.Unknown
|
||||
isTrue := false
|
||||
for _, term := range or.terms {
|
||||
val := term.Eval(ctx)
|
||||
boolVal, ok := val.(types.Bool)
|
||||
// flag the result as true
|
||||
if ok && boolVal == types.True {
|
||||
isTrue = true
|
||||
}
|
||||
if !ok && !isTrue {
|
||||
isUnk := false
|
||||
unk, isUnk = types.MaybeMergeUnknowns(val, unk)
|
||||
if !isUnk && err == nil {
|
||||
if types.IsError(val) {
|
||||
err = val
|
||||
} else {
|
||||
err = types.MaybeNoSuchOverloadErr(val)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if isTrue {
|
||||
return types.True
|
||||
}
|
||||
rBool, rok := rVal.(types.Bool)
|
||||
if rok && rBool == types.True {
|
||||
return types.True
|
||||
if unk != nil {
|
||||
return unk
|
||||
}
|
||||
if lok && rok {
|
||||
return types.False
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if types.IsUnknown(lVal) {
|
||||
return lVal
|
||||
}
|
||||
if types.IsUnknown(rVal) {
|
||||
return rVal
|
||||
}
|
||||
// TODO: Combine the errors into a set in the future.
|
||||
// If the left-hand side is non-boolean return it as the error.
|
||||
if types.IsError(lVal) {
|
||||
return lVal
|
||||
}
|
||||
return types.MaybeNoSuchOverloadErr(rVal)
|
||||
return types.False
|
||||
}
|
||||
|
||||
// evalExhaustiveAnd is just like evalAnd, but does not short-circuit argument evaluation.
|
||||
type evalExhaustiveAnd struct {
|
||||
id int64
|
||||
lhs Interpretable
|
||||
rhs Interpretable
|
||||
id int64
|
||||
terms []Interpretable
|
||||
}
|
||||
|
||||
// ID implements the Interpretable interface method.
|
||||
@ -1039,38 +1099,45 @@ func (and *evalExhaustiveAnd) ID() int64 {
|
||||
|
||||
// Eval implements the Interpretable interface method.
|
||||
func (and *evalExhaustiveAnd) Eval(ctx Activation) ref.Val {
|
||||
lVal := and.lhs.Eval(ctx)
|
||||
rVal := and.rhs.Eval(ctx)
|
||||
lBool, lok := lVal.(types.Bool)
|
||||
if lok && lBool == types.False {
|
||||
var err ref.Val = nil
|
||||
var unk *types.Unknown
|
||||
isFalse := false
|
||||
for _, term := range and.terms {
|
||||
val := term.Eval(ctx)
|
||||
boolVal, ok := val.(types.Bool)
|
||||
// short-circuit on false.
|
||||
if ok && boolVal == types.False {
|
||||
isFalse = true
|
||||
}
|
||||
if !ok && !isFalse {
|
||||
isUnk := false
|
||||
unk, isUnk = types.MaybeMergeUnknowns(val, unk)
|
||||
if !isUnk && err == nil {
|
||||
if types.IsError(val) {
|
||||
err = val
|
||||
} else {
|
||||
err = types.MaybeNoSuchOverloadErr(val)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if isFalse {
|
||||
return types.False
|
||||
}
|
||||
rBool, rok := rVal.(types.Bool)
|
||||
if rok && rBool == types.False {
|
||||
return types.False
|
||||
if unk != nil {
|
||||
return unk
|
||||
}
|
||||
if lok && rok {
|
||||
return types.True
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if types.IsUnknown(lVal) {
|
||||
return lVal
|
||||
}
|
||||
if types.IsUnknown(rVal) {
|
||||
return rVal
|
||||
}
|
||||
// TODO: Combine the errors into a set in the future.
|
||||
// If the left-hand side is non-boolean return it as the error.
|
||||
if types.IsError(lVal) {
|
||||
return lVal
|
||||
}
|
||||
return types.MaybeNoSuchOverloadErr(rVal)
|
||||
return types.True
|
||||
}
|
||||
|
||||
// evalExhaustiveConditional is like evalConditional, but does not short-circuit argument
|
||||
// evaluation.
|
||||
type evalExhaustiveConditional struct {
|
||||
id int64
|
||||
adapter ref.TypeAdapter
|
||||
adapter types.Adapter
|
||||
attr *conditionalAttribute
|
||||
}
|
||||
|
||||
@ -1102,7 +1169,7 @@ func (cond *evalExhaustiveConditional) Eval(ctx Activation) ref.Val {
|
||||
|
||||
// evalAttr evaluates an Attribute value.
|
||||
type evalAttr struct {
|
||||
adapter ref.TypeAdapter
|
||||
adapter types.Adapter
|
||||
attr Attribute
|
||||
optional bool
|
||||
}
|
||||
@ -1127,7 +1194,7 @@ func (a *evalAttr) Attr() Attribute {
|
||||
}
|
||||
|
||||
// Adapter implements the InterpretableAttribute interface method.
|
||||
func (a *evalAttr) Adapter() ref.TypeAdapter {
|
||||
func (a *evalAttr) Adapter() types.Adapter {
|
||||
return a.adapter
|
||||
}
|
||||
|
||||
|
28
vendor/github.com/google/cel-go/interpreter/interpreter.go
generated
vendored
28
vendor/github.com/google/cel-go/interpreter/interpreter.go
generated
vendored
@ -18,9 +18,10 @@
|
||||
package interpreter
|
||||
|
||||
import (
|
||||
"github.com/google/cel-go/common/ast"
|
||||
"github.com/google/cel-go/common/containers"
|
||||
"github.com/google/cel-go/common/types"
|
||||
"github.com/google/cel-go/common/types/ref"
|
||||
"github.com/google/cel-go/interpreter/functions"
|
||||
|
||||
exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
|
||||
)
|
||||
@ -29,7 +30,7 @@ import (
|
||||
type Interpreter interface {
|
||||
// NewInterpretable creates an Interpretable from a checked expression and an
|
||||
// optional list of InterpretableDecorator values.
|
||||
NewInterpretable(checked *exprpb.CheckedExpr, decorators ...InterpretableDecorator) (Interpretable, error)
|
||||
NewInterpretable(checked *ast.CheckedAST, decorators ...InterpretableDecorator) (Interpretable, error)
|
||||
|
||||
// NewUncheckedInterpretable returns an Interpretable from a parsed expression
|
||||
// and an optional list of InterpretableDecorator values.
|
||||
@ -154,8 +155,8 @@ func CompileRegexConstants(regexOptimizations ...*RegexOptimization) Interpretab
|
||||
type exprInterpreter struct {
|
||||
dispatcher Dispatcher
|
||||
container *containers.Container
|
||||
provider ref.TypeProvider
|
||||
adapter ref.TypeAdapter
|
||||
provider types.Provider
|
||||
adapter types.Adapter
|
||||
attrFactory AttributeFactory
|
||||
}
|
||||
|
||||
@ -163,8 +164,8 @@ type exprInterpreter struct {
|
||||
// throughout the Eval of all Interpretable instances generated from it.
|
||||
func NewInterpreter(dispatcher Dispatcher,
|
||||
container *containers.Container,
|
||||
provider ref.TypeProvider,
|
||||
adapter ref.TypeAdapter,
|
||||
provider types.Provider,
|
||||
adapter types.Adapter,
|
||||
attrFactory AttributeFactory) Interpreter {
|
||||
return &exprInterpreter{
|
||||
dispatcher: dispatcher,
|
||||
@ -174,20 +175,9 @@ func NewInterpreter(dispatcher Dispatcher,
|
||||
attrFactory: attrFactory}
|
||||
}
|
||||
|
||||
// NewStandardInterpreter builds a Dispatcher and TypeProvider with support for all of the CEL
|
||||
// builtins defined in the language definition.
|
||||
func NewStandardInterpreter(container *containers.Container,
|
||||
provider ref.TypeProvider,
|
||||
adapter ref.TypeAdapter,
|
||||
resolver AttributeFactory) Interpreter {
|
||||
dispatcher := NewDispatcher()
|
||||
dispatcher.Add(functions.StandardOverloads()...)
|
||||
return NewInterpreter(dispatcher, container, provider, adapter, resolver)
|
||||
}
|
||||
|
||||
// NewIntepretable implements the Interpreter interface method.
|
||||
func (i *exprInterpreter) NewInterpretable(
|
||||
checked *exprpb.CheckedExpr,
|
||||
checked *ast.CheckedAST,
|
||||
decorators ...InterpretableDecorator) (Interpretable, error) {
|
||||
p := newPlanner(
|
||||
i.dispatcher,
|
||||
@ -197,7 +187,7 @@ func (i *exprInterpreter) NewInterpretable(
|
||||
i.container,
|
||||
checked,
|
||||
decorators...)
|
||||
return p.Plan(checked.GetExpr())
|
||||
return p.Plan(checked.Expr)
|
||||
}
|
||||
|
||||
// NewUncheckedIntepretable implements the Interpreter interface method.
|
||||
|
65
vendor/github.com/google/cel-go/interpreter/planner.go
generated
vendored
65
vendor/github.com/google/cel-go/interpreter/planner.go
generated
vendored
@ -18,10 +18,12 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/google/cel-go/common/ast"
|
||||
"github.com/google/cel-go/common/containers"
|
||||
"github.com/google/cel-go/common/functions"
|
||||
"github.com/google/cel-go/common/operators"
|
||||
"github.com/google/cel-go/common/types"
|
||||
"github.com/google/cel-go/common/types/ref"
|
||||
"github.com/google/cel-go/interpreter/functions"
|
||||
|
||||
exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
|
||||
)
|
||||
@ -37,11 +39,11 @@ type interpretablePlanner interface {
|
||||
// functions, types, and namespaced identifiers at plan time rather than at runtime since
|
||||
// it only needs to be done once and may be semi-expensive to compute.
|
||||
func newPlanner(disp Dispatcher,
|
||||
provider ref.TypeProvider,
|
||||
adapter ref.TypeAdapter,
|
||||
provider types.Provider,
|
||||
adapter types.Adapter,
|
||||
attrFactory AttributeFactory,
|
||||
cont *containers.Container,
|
||||
checked *exprpb.CheckedExpr,
|
||||
checked *ast.CheckedAST,
|
||||
decorators ...InterpretableDecorator) interpretablePlanner {
|
||||
return &planner{
|
||||
disp: disp,
|
||||
@ -49,8 +51,8 @@ func newPlanner(disp Dispatcher,
|
||||
adapter: adapter,
|
||||
attrFactory: attrFactory,
|
||||
container: cont,
|
||||
refMap: checked.GetReferenceMap(),
|
||||
typeMap: checked.GetTypeMap(),
|
||||
refMap: checked.ReferenceMap,
|
||||
typeMap: checked.TypeMap,
|
||||
decorators: decorators,
|
||||
}
|
||||
}
|
||||
@ -59,8 +61,8 @@ func newPlanner(disp Dispatcher,
|
||||
// TypeAdapter, and Container to resolve functions and types at plan time. Namespaces present in
|
||||
// Select expressions are resolved lazily at evaluation time.
|
||||
func newUncheckedPlanner(disp Dispatcher,
|
||||
provider ref.TypeProvider,
|
||||
adapter ref.TypeAdapter,
|
||||
provider types.Provider,
|
||||
adapter types.Adapter,
|
||||
attrFactory AttributeFactory,
|
||||
cont *containers.Container,
|
||||
decorators ...InterpretableDecorator) interpretablePlanner {
|
||||
@ -70,8 +72,8 @@ func newUncheckedPlanner(disp Dispatcher,
|
||||
adapter: adapter,
|
||||
attrFactory: attrFactory,
|
||||
container: cont,
|
||||
refMap: make(map[int64]*exprpb.Reference),
|
||||
typeMap: make(map[int64]*exprpb.Type),
|
||||
refMap: make(map[int64]*ast.ReferenceInfo),
|
||||
typeMap: make(map[int64]*types.Type),
|
||||
decorators: decorators,
|
||||
}
|
||||
}
|
||||
@ -79,12 +81,12 @@ func newUncheckedPlanner(disp Dispatcher,
|
||||
// planner is an implementation of the interpretablePlanner interface.
|
||||
type planner struct {
|
||||
disp Dispatcher
|
||||
provider ref.TypeProvider
|
||||
adapter ref.TypeAdapter
|
||||
provider types.Provider
|
||||
adapter types.Adapter
|
||||
attrFactory AttributeFactory
|
||||
container *containers.Container
|
||||
refMap map[int64]*exprpb.Reference
|
||||
typeMap map[int64]*exprpb.Type
|
||||
refMap map[int64]*ast.ReferenceInfo
|
||||
typeMap map[int64]*types.Type
|
||||
decorators []InterpretableDecorator
|
||||
}
|
||||
|
||||
@ -143,22 +145,19 @@ func (p *planner) planIdent(expr *exprpb.Expr) (Interpretable, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *planner) planCheckedIdent(id int64, identRef *exprpb.Reference) (Interpretable, error) {
|
||||
func (p *planner) planCheckedIdent(id int64, identRef *ast.ReferenceInfo) (Interpretable, error) {
|
||||
// Plan a constant reference if this is the case for this simple identifier.
|
||||
if identRef.GetValue() != nil {
|
||||
return p.Plan(&exprpb.Expr{Id: id,
|
||||
ExprKind: &exprpb.Expr_ConstExpr{
|
||||
ConstExpr: identRef.GetValue(),
|
||||
}})
|
||||
if identRef.Value != nil {
|
||||
return NewConstValue(id, identRef.Value), nil
|
||||
}
|
||||
|
||||
// Check to see whether the type map indicates this is a type name. All types should be
|
||||
// registered with the provider.
|
||||
cType := p.typeMap[id]
|
||||
if cType.GetType() != nil {
|
||||
cVal, found := p.provider.FindIdent(identRef.GetName())
|
||||
if cType.Kind() == types.TypeKind {
|
||||
cVal, found := p.provider.FindIdent(identRef.Name)
|
||||
if !found {
|
||||
return nil, fmt.Errorf("reference to undefined type: %s", identRef.GetName())
|
||||
return nil, fmt.Errorf("reference to undefined type: %s", identRef.Name)
|
||||
}
|
||||
return NewConstValue(id, cVal), nil
|
||||
}
|
||||
@ -166,7 +165,7 @@ func (p *planner) planCheckedIdent(id int64, identRef *exprpb.Reference) (Interp
|
||||
// Otherwise, return the attribute for the resolved identifier name.
|
||||
return &evalAttr{
|
||||
adapter: p.adapter,
|
||||
attr: p.attrFactory.AbsoluteAttribute(id, identRef.GetName()),
|
||||
attr: p.attrFactory.AbsoluteAttribute(id, identRef.Name),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -429,18 +428,16 @@ func (p *planner) planCallNotEqual(expr *exprpb.Expr, args []Interpretable) (Int
|
||||
// planCallLogicalAnd generates a logical and (&&) Interpretable.
|
||||
func (p *planner) planCallLogicalAnd(expr *exprpb.Expr, args []Interpretable) (Interpretable, error) {
|
||||
return &evalAnd{
|
||||
id: expr.GetId(),
|
||||
lhs: args[0],
|
||||
rhs: args[1],
|
||||
id: expr.GetId(),
|
||||
terms: args,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// planCallLogicalOr generates a logical or (||) Interpretable.
|
||||
func (p *planner) planCallLogicalOr(expr *exprpb.Expr, args []Interpretable) (Interpretable, error) {
|
||||
return &evalOr{
|
||||
id: expr.GetId(),
|
||||
lhs: args[0],
|
||||
rhs: args[1],
|
||||
id: expr.GetId(),
|
||||
terms: args,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -476,7 +473,7 @@ func (p *planner) planCallConditional(expr *exprpb.Expr, args []Interpretable) (
|
||||
func (p *planner) planCallIndex(expr *exprpb.Expr, args []Interpretable, optional bool) (Interpretable, error) {
|
||||
op := args[0]
|
||||
ind := args[1]
|
||||
opType := p.typeMap[expr.GetCallExpr().GetTarget().GetId()]
|
||||
opType := p.typeMap[op.ID()]
|
||||
|
||||
// Establish the attribute reference.
|
||||
var err error
|
||||
@ -675,7 +672,7 @@ func (p *planner) constValue(c *exprpb.Constant) (ref.Val, error) {
|
||||
// namespace resolution rules to it in a scan over possible matching types in the TypeProvider.
|
||||
func (p *planner) resolveTypeName(typeName string) (string, bool) {
|
||||
for _, qualifiedTypeName := range p.container.ResolveCandidateNames(typeName) {
|
||||
if _, found := p.provider.FindType(qualifiedTypeName); found {
|
||||
if _, found := p.provider.FindStructType(qualifiedTypeName); found {
|
||||
return qualifiedTypeName, true
|
||||
}
|
||||
}
|
||||
@ -702,8 +699,8 @@ func (p *planner) resolveFunction(expr *exprpb.Expr) (*exprpb.Expr, string, stri
|
||||
// function name as the fnName value.
|
||||
oRef, hasOverload := p.refMap[expr.GetId()]
|
||||
if hasOverload {
|
||||
if len(oRef.GetOverloadId()) == 1 {
|
||||
return target, fnName, oRef.GetOverloadId()[0]
|
||||
if len(oRef.OverloadIDs) == 1 {
|
||||
return target, fnName, oRef.OverloadIDs[0]
|
||||
}
|
||||
// Note, this namespaced function name will not appear as a fully qualified name in ASTs
|
||||
// built and stored before cel-go v0.5.0; however, this functionality did not work at all
|
||||
|
45
vendor/github.com/google/cel-go/interpreter/prune.go
generated
vendored
45
vendor/github.com/google/cel-go/interpreter/prune.go
generated
vendored
@ -341,6 +341,11 @@ func (p *astPruner) prune(node *exprpb.Expr) (*exprpb.Expr, bool) {
|
||||
}
|
||||
}
|
||||
if macro, found := p.macroCalls[node.GetId()]; found {
|
||||
// Ensure that intermediate values for the comprehension are cleared during pruning
|
||||
compre := node.GetComprehensionExpr()
|
||||
if compre != nil {
|
||||
visit(macro, clearIterVarVisitor(compre.IterVar, p.state))
|
||||
}
|
||||
// prune the expression in terms of the macro call instead of the expanded form.
|
||||
if newMacro, pruned := p.prune(macro); pruned {
|
||||
p.macroCalls[node.GetId()] = newMacro
|
||||
@ -488,6 +493,27 @@ func (p *astPruner) prune(node *exprpb.Expr) (*exprpb.Expr, bool) {
|
||||
},
|
||||
}, true
|
||||
}
|
||||
case *exprpb.Expr_ComprehensionExpr:
|
||||
compre := node.GetComprehensionExpr()
|
||||
// Only the range of the comprehension is pruned since the state tracking only records
|
||||
// the last iteration of the comprehension and not each step in the evaluation which
|
||||
// means that the any residuals computed in between might be inaccurate.
|
||||
if newRange, pruned := p.maybePrune(compre.GetIterRange()); pruned {
|
||||
return &exprpb.Expr{
|
||||
Id: node.GetId(),
|
||||
ExprKind: &exprpb.Expr_ComprehensionExpr{
|
||||
ComprehensionExpr: &exprpb.Expr_Comprehension{
|
||||
IterVar: compre.GetIterVar(),
|
||||
IterRange: newRange,
|
||||
AccuVar: compre.GetAccuVar(),
|
||||
AccuInit: compre.GetAccuInit(),
|
||||
LoopCondition: compre.GetLoopCondition(),
|
||||
LoopStep: compre.GetLoopStep(),
|
||||
Result: compre.GetResult(),
|
||||
},
|
||||
},
|
||||
}, true
|
||||
}
|
||||
}
|
||||
return node, false
|
||||
}
|
||||
@ -524,6 +550,17 @@ func getMaxID(expr *exprpb.Expr) int64 {
|
||||
return maxID
|
||||
}
|
||||
|
||||
func clearIterVarVisitor(varName string, state EvalState) astVisitor {
|
||||
return astVisitor{
|
||||
visitExpr: func(e *exprpb.Expr) {
|
||||
ident := e.GetIdentExpr()
|
||||
if ident != nil && ident.GetName() == varName {
|
||||
state.SetValue(e.GetId(), nil)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func maxIDVisitor(maxID *int64) astVisitor {
|
||||
return astVisitor{
|
||||
visitExpr: func(e *exprpb.Expr) {
|
||||
@ -543,7 +580,9 @@ func visit(expr *exprpb.Expr, visitor astVisitor) {
|
||||
exprs := []*exprpb.Expr{expr}
|
||||
for len(exprs) != 0 {
|
||||
e := exprs[0]
|
||||
visitor.visitExpr(e)
|
||||
if visitor.visitExpr != nil {
|
||||
visitor.visitExpr(e)
|
||||
}
|
||||
exprs = exprs[1:]
|
||||
switch e.GetExprKind().(type) {
|
||||
case *exprpb.Expr_SelectExpr:
|
||||
@ -567,7 +606,9 @@ func visit(expr *exprpb.Expr, visitor astVisitor) {
|
||||
exprs = append(exprs, list.GetElements()...)
|
||||
case *exprpb.Expr_StructExpr:
|
||||
for _, entry := range e.GetStructExpr().GetEntries() {
|
||||
visitor.visitEntry(entry)
|
||||
if visitor.visitEntry != nil {
|
||||
visitor.visitEntry(entry)
|
||||
}
|
||||
if entry.GetMapKey() != nil {
|
||||
exprs = append(exprs, entry.GetMapKey())
|
||||
}
|
||||
|
63
vendor/github.com/google/cel-go/interpreter/runtimecost.go
generated
vendored
63
vendor/github.com/google/cel-go/interpreter/runtimecost.go
generated
vendored
@ -65,13 +65,21 @@ func CostObserver(tracker *CostTracker) EvalObserver {
|
||||
// While the field names are identical, the boolean operation eval structs do not share an interface and so
|
||||
// must be handled individually.
|
||||
case *evalOr:
|
||||
tracker.stack.drop(t.rhs.ID(), t.lhs.ID())
|
||||
for _, term := range t.terms {
|
||||
tracker.stack.drop(term.ID())
|
||||
}
|
||||
case *evalAnd:
|
||||
tracker.stack.drop(t.rhs.ID(), t.lhs.ID())
|
||||
for _, term := range t.terms {
|
||||
tracker.stack.drop(term.ID())
|
||||
}
|
||||
case *evalExhaustiveOr:
|
||||
tracker.stack.drop(t.rhs.ID(), t.lhs.ID())
|
||||
for _, term := range t.terms {
|
||||
tracker.stack.drop(term.ID())
|
||||
}
|
||||
case *evalExhaustiveAnd:
|
||||
tracker.stack.drop(t.rhs.ID(), t.lhs.ID())
|
||||
for _, term := range t.terms {
|
||||
tracker.stack.drop(term.ID())
|
||||
}
|
||||
case *evalFold:
|
||||
tracker.stack.drop(t.iterRange.ID())
|
||||
case Qualifier:
|
||||
@ -125,6 +133,7 @@ func PresenceTestHasCost(hasCost bool) CostTrackerOption {
|
||||
func NewCostTracker(estimator ActualCostEstimator, opts ...CostTrackerOption) (*CostTracker, error) {
|
||||
tracker := &CostTracker{
|
||||
Estimator: estimator,
|
||||
overloadTrackers: map[string]FunctionTracker{},
|
||||
presenceTestHasCost: true,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
@ -136,9 +145,24 @@ func NewCostTracker(estimator ActualCostEstimator, opts ...CostTrackerOption) (*
|
||||
return tracker, nil
|
||||
}
|
||||
|
||||
// OverloadCostTracker binds an overload ID to a runtime FunctionTracker implementation.
|
||||
//
|
||||
// OverloadCostTracker instances augment or override ActualCostEstimator decisions, allowing for versioned and/or
|
||||
// optional cost tracking changes.
|
||||
func OverloadCostTracker(overloadID string, fnTracker FunctionTracker) CostTrackerOption {
|
||||
return func(tracker *CostTracker) error {
|
||||
tracker.overloadTrackers[overloadID] = fnTracker
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// FunctionTracker computes the actual cost of evaluating the functions with the given arguments and result.
|
||||
type FunctionTracker func(args []ref.Val, result ref.Val) *uint64
|
||||
|
||||
// CostTracker represents the information needed for tracking runtime cost.
|
||||
type CostTracker struct {
|
||||
Estimator ActualCostEstimator
|
||||
overloadTrackers map[string]FunctionTracker
|
||||
Limit *uint64
|
||||
presenceTestHasCost bool
|
||||
|
||||
@ -151,10 +175,19 @@ func (c *CostTracker) ActualCost() uint64 {
|
||||
return c.cost
|
||||
}
|
||||
|
||||
func (c *CostTracker) costCall(call InterpretableCall, argValues []ref.Val, result ref.Val) uint64 {
|
||||
func (c *CostTracker) costCall(call InterpretableCall, args []ref.Val, result ref.Val) uint64 {
|
||||
var cost uint64
|
||||
if len(c.overloadTrackers) != 0 {
|
||||
if tracker, found := c.overloadTrackers[call.OverloadID()]; found {
|
||||
callCost := tracker(args, result)
|
||||
if callCost != nil {
|
||||
cost += *callCost
|
||||
return cost
|
||||
}
|
||||
}
|
||||
}
|
||||
if c.Estimator != nil {
|
||||
callCost := c.Estimator.CallCost(call.Function(), call.OverloadID(), argValues, result)
|
||||
callCost := c.Estimator.CallCost(call.Function(), call.OverloadID(), args, result)
|
||||
if callCost != nil {
|
||||
cost += *callCost
|
||||
return cost
|
||||
@ -165,11 +198,11 @@ func (c *CostTracker) costCall(call InterpretableCall, argValues []ref.Val, resu
|
||||
switch call.OverloadID() {
|
||||
// O(n) functions
|
||||
case overloads.StartsWithString, overloads.EndsWithString, overloads.StringToBytes, overloads.BytesToString, overloads.ExtQuoteString, overloads.ExtFormatString:
|
||||
cost += uint64(math.Ceil(float64(c.actualSize(argValues[0])) * common.StringTraversalCostFactor))
|
||||
cost += uint64(math.Ceil(float64(c.actualSize(args[0])) * common.StringTraversalCostFactor))
|
||||
case overloads.InList:
|
||||
// If a list is composed entirely of constant values this is O(1), but we don't account for that here.
|
||||
// We just assume all list containment checks are O(n).
|
||||
cost += c.actualSize(argValues[1])
|
||||
cost += c.actualSize(args[1])
|
||||
// O(min(m, n)) functions
|
||||
case overloads.LessString, overloads.GreaterString, overloads.LessEqualsString, overloads.GreaterEqualsString,
|
||||
overloads.LessBytes, overloads.GreaterBytes, overloads.LessEqualsBytes, overloads.GreaterEqualsBytes,
|
||||
@ -177,8 +210,8 @@ func (c *CostTracker) costCall(call InterpretableCall, argValues []ref.Val, resu
|
||||
// When we check the equality of 2 scalar values (e.g. 2 integers, 2 floating-point numbers, 2 booleans etc.),
|
||||
// the CostTracker.actualSize() function by definition returns 1 for each operand, resulting in an overall cost
|
||||
// of 1.
|
||||
lhsSize := c.actualSize(argValues[0])
|
||||
rhsSize := c.actualSize(argValues[1])
|
||||
lhsSize := c.actualSize(args[0])
|
||||
rhsSize := c.actualSize(args[1])
|
||||
minSize := lhsSize
|
||||
if rhsSize < minSize {
|
||||
minSize = rhsSize
|
||||
@ -187,23 +220,23 @@ func (c *CostTracker) costCall(call InterpretableCall, argValues []ref.Val, resu
|
||||
// O(m+n) functions
|
||||
case overloads.AddString, overloads.AddBytes:
|
||||
// In the worst case scenario, we would need to reallocate a new backing store and copy both operands over.
|
||||
cost += uint64(math.Ceil(float64(c.actualSize(argValues[0])+c.actualSize(argValues[1])) * common.StringTraversalCostFactor))
|
||||
cost += uint64(math.Ceil(float64(c.actualSize(args[0])+c.actualSize(args[1])) * common.StringTraversalCostFactor))
|
||||
// O(nm) functions
|
||||
case overloads.MatchesString:
|
||||
// https://swtch.com/~rsc/regexp/regexp1.html applies to RE2 implementation supported by CEL
|
||||
// Add one to string length for purposes of cost calculation to prevent product of string and regex to be 0
|
||||
// in case where string is empty but regex is still expensive.
|
||||
strCost := uint64(math.Ceil((1.0 + float64(c.actualSize(argValues[0]))) * common.StringTraversalCostFactor))
|
||||
strCost := uint64(math.Ceil((1.0 + float64(c.actualSize(args[0]))) * common.StringTraversalCostFactor))
|
||||
// We don't know how many expressions are in the regex, just the string length (a huge
|
||||
// improvement here would be to somehow get a count the number of expressions in the regex or
|
||||
// how many states are in the regex state machine and use that to measure regex cost).
|
||||
// For now, we're making a guess that each expression in a regex is typically at least 4 chars
|
||||
// in length.
|
||||
regexCost := uint64(math.Ceil(float64(c.actualSize(argValues[1])) * common.RegexStringLengthCostFactor))
|
||||
regexCost := uint64(math.Ceil(float64(c.actualSize(args[1])) * common.RegexStringLengthCostFactor))
|
||||
cost += strCost * regexCost
|
||||
case overloads.ContainsString:
|
||||
strCost := uint64(math.Ceil(float64(c.actualSize(argValues[0])) * common.StringTraversalCostFactor))
|
||||
substrCost := uint64(math.Ceil(float64(c.actualSize(argValues[1])) * common.StringTraversalCostFactor))
|
||||
strCost := uint64(math.Ceil(float64(c.actualSize(args[0])) * common.StringTraversalCostFactor))
|
||||
substrCost := uint64(math.Ceil(float64(c.actualSize(args[1])) * common.StringTraversalCostFactor))
|
||||
cost += strCost * substrCost
|
||||
|
||||
default:
|
||||
|
Reference in New Issue
Block a user