func (bin *evalBinary) Cost() (min, max int64) {
	return calExhaustiveBinaryOpsCost(bin.lhs, bin.rhs)
}
Cost implements the Coster interface method.
package interpreter
import (
	"math"
	"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"
)
type Interpretable interface {
	ID() int64
	Eval(activation Activation) ref.Val
}
type InterpretableConst interface {
	Interpretable
	Value() ref.Val
}
type InterpretableAttribute interface {
	Interpretable
	Attr() Attribute
	Adapter() ref.TypeAdapter
	AddQualifier(Qualifier) (Attribute, error)
	Qualify(vars Activation, obj interface{}) (interface{}, error)
	Resolve(Activation) (interface{}, error)
}
type InterpretableCall interface {
	Interpretable
	Function() string
	OverloadID() string
	Args() []Interpretable
}
type evalTestOnly struct {
	id        int64
	op        Interpretable
	field     types.String
	fieldType *ref.FieldType
}
func (test *evalTestOnly) ID() int64 {
	return test.id
}
func (test *evalTestOnly) Eval(ctx Activation) ref.Val {
	if test.fieldType != nil {
		opAttr, ok := test.op.(InterpretableAttribute)
		if ok {
			opVal, err := opAttr.Resolve(ctx)
			if err != nil {
				return types.NewErr(err.Error())
			}
			refVal, ok := opVal.(ref.Val)
			if ok {
				opVal = refVal.Value()
			}
			if test.fieldType.IsSet(opVal) {
				return types.True
			}
			return types.False
		}
	}
	obj := test.op.Eval(ctx)
	tester, ok := obj.(traits.FieldTester)
	if ok {
		return tester.IsSet(test.field)
	}
	container, ok := obj.(traits.Container)
	if ok {
		return container.Contains(test.field)
	}
	return types.ValOrErr(obj, "invalid type for field selection.")
}
func (test *evalTestOnly) Cost() (min, max int64) {
	min, max = estimateCost(test.op)
	min++
	max++
	return
}
func NewConstValue(id int64, val ref.Val) InterpretableConst {
	return &evalConst{
		id:  id,
		val: val,
	}
}
type evalConst struct {
	id  int64
	val ref.Val
}
func (cons *evalConst) ID() int64 {
	return cons.id
}
func (cons *evalConst) Eval(ctx Activation) ref.Val {
	return cons.val
}
func (cons *evalConst) Cost() (min, max int64) {
	return 0, 0
}
func (cons *evalConst) Value() ref.Val {
	return cons.val
}
type evalOr struct {
	id  int64
	lhs Interpretable
	rhs Interpretable
}
func (or *evalOr) ID() int64 {
	return or.id
}
func (or *evalOr) Eval(ctx Activation) ref.Val {
	lVal := or.lhs.Eval(ctx)
	lBool, lok := lVal.(types.Bool)
	if lok && lBool == types.True {
		return types.True
	}
	rVal := or.rhs.Eval(ctx)
	rBool, rok := rVal.(types.Bool)
	if rok && rBool == types.True {
		return types.True
	}
	if lok && rok {
		return types.False
	}
	if types.IsUnknown(lVal) {
		return lVal
	}
	if types.IsUnknown(rVal) {
		return rVal
	}
	if types.IsError(lVal) {
		return lVal
	}
	return types.ValOrErr(rVal, "no such overload")
}
func (or *evalOr) Cost() (min, max int64) {
	return calShortCircuitBinaryOpsCost(or.lhs, or.rhs)
}
type evalAnd struct {
	id  int64
	lhs Interpretable
	rhs Interpretable
}
func (and *evalAnd) ID() int64 {
	return and.id
}
func (and *evalAnd) Eval(ctx Activation) ref.Val {
	lVal := and.lhs.Eval(ctx)
	lBool, lok := lVal.(types.Bool)
	if lok && lBool == types.False {
		return types.False
	}
	rVal := and.rhs.Eval(ctx)
	rBool, rok := rVal.(types.Bool)
	if rok && rBool == types.False {
		return types.False
	}
	if lok && rok {
		return types.True
	}
	if types.IsUnknown(lVal) {
		return lVal
	}
	if types.IsUnknown(rVal) {
		return rVal
	}
	if types.IsError(lVal) {
		return lVal
	}
	return types.ValOrErr(rVal, "no such overload")
}
func (and *evalAnd) Cost() (min, max int64) {
	return calShortCircuitBinaryOpsCost(and.lhs, and.rhs)
}
func calShortCircuitBinaryOpsCost(lhs, rhs Interpretable) (min, max int64) {
	lMin, lMax := estimateCost(lhs)
	_, rMax := estimateCost(rhs)
	return lMin, lMax + rMax + 1
}
type evalEq struct {
	id  int64
	lhs Interpretable
	rhs Interpretable
}
func (eq *evalEq) ID() int64 {
	return eq.id
}
func (eq *evalEq) Eval(ctx Activation) ref.Val {
	lVal := eq.lhs.Eval(ctx)
	rVal := eq.rhs.Eval(ctx)
	return lVal.Equal(rVal)
}
func (eq *evalEq) Cost() (min, max int64) {
	return calExhaustiveBinaryOpsCost(eq.lhs, eq.rhs)
}
func (*evalEq) Function() string {
	return operators.Equals
}
func (*evalEq) OverloadID() string {
	return overloads.Equals
}
func (eq *evalEq) Args() []Interpretable {
	return []Interpretable{eq.lhs, eq.rhs}
}
type evalNe struct {
	id  int64
	lhs Interpretable
	rhs Interpretable
}
func (ne *evalNe) ID() int64 {
	return ne.id
}
func (ne *evalNe) Eval(ctx Activation) ref.Val {
	lVal := ne.lhs.Eval(ctx)
	rVal := ne.rhs.Eval(ctx)
	eqVal := lVal.Equal(rVal)
	eqBool, ok := eqVal.(types.Bool)
	if !ok {
		return types.ValOrErr(eqVal, "no such overload: _!=_")
	}
	return !eqBool
}
func (ne *evalNe) Cost() (min, max int64) {
	return calExhaustiveBinaryOpsCost(ne.lhs, ne.rhs)
}
func (*evalNe) Function() string {
	return operators.NotEquals
}
func (*evalNe) OverloadID() string {
	return overloads.NotEquals
}
func (ne *evalNe) Args() []Interpretable {
	return []Interpretable{ne.lhs, ne.rhs}
}
type evalZeroArity struct {
	id       int64
	function string
	overload string
	impl     functions.FunctionOp
}
func (zero *evalZeroArity) ID() int64 {
	return zero.id
}
func (zero *evalZeroArity) Eval(ctx Activation) ref.Val {
	return zero.impl()
}
func (zero *evalZeroArity) Cost() (min, max int64) {
	return 1, 1
}
func (zero *evalZeroArity) Function() string {
	return zero.function
}
func (zero *evalZeroArity) OverloadID() string {
	return zero.overload
}
func (zero *evalZeroArity) Args() []Interpretable {
	return []Interpretable{}
}
type evalUnary struct {
	id       int64
	function string
	overload string
	arg      Interpretable
	trait    int
	impl     functions.UnaryOp
}
func (un *evalUnary) ID() int64 {
	return un.id
}
func (un *evalUnary) Eval(ctx Activation) ref.Val {
	argVal := un.arg.Eval(ctx)
	if types.IsUnknownOrError(argVal) {
		return argVal
	}
	if un.impl != nil && (un.trait == 0 || argVal.Type().HasTrait(un.trait)) {
		return un.impl(argVal)
	}
	if argVal.Type().HasTrait(traits.ReceiverType) {
		return argVal.(traits.Receiver).Receive(un.function, un.overload, []ref.Val{})
	}
	return types.NewErr("no such overload: %s", un.function)
}
func (un *evalUnary) Cost() (min, max int64) {
	min, max = estimateCost(un.arg)
	min++  
	max++
	return
}
func (un *evalUnary) Function() string {
	return un.function
}
func (un *evalUnary) OverloadID() string {
	return un.overload
}
func (un *evalUnary) Args() []Interpretable {
	return []Interpretable{un.arg}
}
type evalBinary struct {
	id       int64
	function string
	overload string
	lhs      Interpretable
	rhs      Interpretable
	trait    int
	impl     functions.BinaryOp
}
func (bin *evalBinary) ID() int64 {
	return bin.id
}
func (bin *evalBinary) Eval(ctx Activation) ref.Val {
	lVal := bin.lhs.Eval(ctx)
	rVal := bin.rhs.Eval(ctx)
	if types.IsUnknownOrError(lVal) {
		return lVal
	}
	if types.IsUnknownOrError(rVal) {
		return rVal
	}
	if bin.impl != nil && (bin.trait == 0 || lVal.Type().HasTrait(bin.trait)) {
		return bin.impl(lVal, rVal)
	}
	if lVal.Type().HasTrait(traits.ReceiverType) {
		return lVal.(traits.Receiver).Receive(bin.function, bin.overload, []ref.Val{rVal})
	}
	return types.NewErr("no such overload: %s", bin.function)
}