cel

package
v0.20.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 7, 2024 License: Apache-2.0, BSD-3-Clause Imports: 34 Imported by: 359

Documentation

Overview

Package cel defines the top-level interface for the Common Expression Language (CEL).

CEL is a non-Turing complete expression language designed to parse, check, and evaluate expressions against user-defined environments.

Example
package main

import (
	"fmt"
	"log"

	"github.com/google/cel-go/cel"
	"github.com/google/cel-go/common/types"
	"github.com/google/cel-go/common/types/ref"
)

func main() {
	// Create the CEL environment with declarations for the input attributes and the extension functions.
	// In many cases the desired functionality will be present in a built-in function.
	e, err := cel.NewEnv(
		// Variable identifiers used within this expression.
		cel.Variable("i", cel.StringType),
		cel.Variable("you", cel.StringType),
		// Function to generate a greeting from one person to another: i.greet(you)
		cel.Function("greet",
			cel.MemberOverload("string_greet_string", []*cel.Type{cel.StringType, cel.StringType}, cel.StringType,
				cel.BinaryBinding(func(lhs, rhs ref.Val) ref.Val {
					return types.String(fmt.Sprintf("Hello %s! Nice to meet you, I'm %s.\n", rhs, lhs))
				}),
			),
		),
	)
	if err != nil {
		log.Fatalf("environment creation error: %s\n", err)
	}

	// Compile the expression.
	ast, iss := e.Compile("i.greet(you)")
	if iss.Err() != nil {
		log.Fatalln(iss.Err())
	}

	// Create the program.
	prg, err := e.Program(ast)
	if err != nil {
		log.Fatalf("program creation error: %s\n", err)
	}

	// Evaluate the program against some inputs. Note: the details return is not used.
	out, _, err := prg.Eval(map[string]any{
		// Native values are converted to CEL values under the covers.
		"i": "CEL",
		// Values may also be lazily supplied.
		"you": func() ref.Val { return types.String("world") },
	})
	if err != nil {
		log.Fatalf("runtime error: %s\n", err)
	}

	fmt.Println(out)
}
Output:

Hello world! Nice to meet you, I'm CEL.
Example (GlobalOverload)
package main

import (
	"fmt"
	"log"

	"github.com/google/cel-go/cel"
	"github.com/google/cel-go/common/types"
	"github.com/google/cel-go/common/types/ref"
)

func main() {
	// The GlobalOverload example demonstrates how to define global overload function.
	// Create the CEL environment with declarations for the input attributes and
	// the desired extension functions. In many cases the desired functionality will
	// be present in a built-in function.
	e, err := cel.NewEnv(
		// Identifiers used within this expression.
		cel.Variable("i", cel.StringType),
		cel.Variable("you", cel.StringType),
		// Function to generate shake_hands between two people.
		//    shake_hands(i,you)
		cel.Function("shake_hands",
			cel.Overload("shake_hands_string_string", []*cel.Type{cel.StringType, cel.StringType}, cel.StringType,
				cel.BinaryBinding(func(arg1, arg2 ref.Val) ref.Val {
					return types.String(fmt.Sprintf("%v and %v are shaking hands.\n", arg1, arg2))
				}),
			),
		),
	)
	if err != nil {
		log.Fatalf("environment creation error: %s\n", err)
	}

	// Compile the expression.
	ast, iss := e.Compile(`shake_hands(i,you)`)
	if iss.Err() != nil {
		log.Fatalln(iss.Err())
	}

	// Create the program.
	prg, err := e.Program(ast)
	if err != nil {
		log.Fatalf("program creation error: %s\n", err)
	}

	// Evaluate the program against some inputs. Note: the details return is not used.
	out, _, err := prg.Eval(map[string]any{
		"i":   "CEL",
		"you": func() ref.Val { return types.String("world") },
	})
	if err != nil {
		log.Fatalf("runtime error: %s\n", err)
	}

	fmt.Println(out)
}
Output:

CEL and world are shaking hands.
Example (StatefulOverload)
package main

import (
	"context"
	"fmt"
	"log"

	"github.com/google/cel-go/cel"
	"github.com/google/cel-go/common/types"
	"github.com/google/cel-go/common/types/ref"
)

func main() {
	// makeFetch produces a consistent function signature with a different function
	// implementation depending on the provided context.
	makeFetch := func(ctx any) cel.EnvOption {
		fn := func(arg ref.Val) ref.Val {
			return types.NewErr("stateful context not bound")
		}
		if ctx != nil {
			fn = func(resource ref.Val) ref.Val {
				return types.DefaultTypeAdapter.NativeToValue(
					ctx.(context.Context).Value(contextString(string(resource.(types.String)))),
				)
			}
		}
		return cel.Function("fetch",
			cel.Overload("fetch_string",
				[]*cel.Type{cel.StringType}, cel.StringType,
				cel.UnaryBinding(fn),
			),
		)
	}

	// The base environment declares the fetch function with a dummy binding that errors
	// if it is invoked without being replaced by a subsequent call to `baseEnv.Extend`
	baseEnv, err := cel.NewEnv(
		// Identifiers used within this expression.
		cel.Variable("resource", cel.StringType),
		// Function to fetch a resource.
		//    fetch(resource)
		makeFetch(nil),
	)
	if err != nil {
		log.Fatalf("environment creation error: %s\n", err)
	}
	ast, iss := baseEnv.Compile("fetch('my-resource') == 'my-value'")
	if iss.Err() != nil {
		log.Fatalf("Compile() failed: %v", iss.Err())
	}

	// The runtime environment extends the base environment with a contextual binding for
	// the 'fetch' function.
	ctx := context.WithValue(context.TODO(), contextString("my-resource"), "my-value")
	runtimeEnv, err := baseEnv.Extend(makeFetch(ctx))
	if err != nil {
		log.Fatalf("baseEnv.Extend() failed with error: %s\n", err)
	}
	prg, err := runtimeEnv.Program(ast)
	if err != nil {
		log.Fatalf("runtimeEnv.Program() error: %s\n", err)
	}
	out, _, err := prg.Eval(cel.NoVars())
	if err != nil {
		log.Fatalf("runtime error: %s\n", err)
	}

	fmt.Println(out)
}

type contextString string
Output:

true

Index

Examples

Constants

View Source
const (
	// DynKind represents a dynamic type. This kind only exists at type-check time.
	DynKind Kind = types.DynKind

	// AnyKind represents a google.protobuf.Any type. This kind only exists at type-check time.
	AnyKind = types.AnyKind

	// BoolKind represents a boolean type.
	BoolKind = types.BoolKind

	// BytesKind represents a bytes type.
	BytesKind = types.BytesKind

	// DoubleKind represents a double type.
	DoubleKind = types.DoubleKind

	// DurationKind represents a CEL duration type.
	DurationKind = types.DurationKind

	// IntKind represents an integer type.
	IntKind = types.IntKind

	// ListKind represents a list type.
	ListKind = types.ListKind

	// MapKind represents a map type.
	MapKind = types.MapKind

	// NullTypeKind represents a null type.
	NullTypeKind = types.NullTypeKind

	// OpaqueKind represents an abstract type which has no accessible fields.
	OpaqueKind = types.OpaqueKind

	// StringKind represents a string type.
	StringKind = types.StringKind

	// StructKind represents a structured object with typed fields.
	StructKind = types.StructKind

	// TimestampKind represents a a CEL time type.
	TimestampKind = types.TimestampKind

	// TypeKind represents the CEL type.
	TypeKind = types.TypeKind

	// TypeParamKind represents a parameterized type whose type name will be resolved at type-check time, if possible.
	TypeParamKind = types.TypeParamKind

	// UintKind represents a uint type.
	UintKind = types.UintKind
)
View Source
const (

	// HomogeneousAggregateLiteralExemptFunctions is the ValidatorConfig key used to configure
	// the set of function names which are exempt from homogeneous type checks. The expected type
	// is a string list of function names.
	//
	// As an example, the `<string>.format([args])` call expects the input arguments list to be
	// comprised of a variety of types which correspond to the types expected by the format control
	// clauses; however, all other uses of a mixed element type list, would be unexpected.
	HomogeneousAggregateLiteralExemptFunctions = homogeneousValidatorName + ".exempt"
)

Variables

View Source
var (
	// AnyType represents the google.protobuf.Any type.
	AnyType = types.AnyType
	// BoolType represents the bool type.
	BoolType = types.BoolType
	// BytesType represents the bytes type.
	BytesType = types.BytesType
	// DoubleType represents the double type.
	DoubleType = types.DoubleType
	// DurationType represents the CEL duration type.
	DurationType = types.DurationType
	// DynType represents a dynamic CEL type whose type will be determined at runtime from context.
	DynType = types.DynType
	// IntType represents the int type.
	IntType = types.IntType
	// NullType represents the type of a null value.
	NullType = types.NullType
	// StringType represents the string type.
	StringType = types.StringType
	// TimestampType represents the time type.
	TimestampType = types.TimestampType
	// TypeType represents a CEL type
	TypeType = types.TypeType
	// UintType represents a uint type.
	UintType = types.UintType

	// ListType creates an instances of a list type value with the provided element type.
	ListType = types.NewListType
	// MapType creates an instance of a map type value with the provided key and value types.
	MapType = types.NewMapType
	// NullableType creates an instance of a nullable type with the provided wrapped type.
	//
	// Note: only primitive types are supported as wrapped types.
	NullableType = types.NewNullableType
	// OptionalType creates an abstract parameterized type instance corresponding to CEL's notion of optional.
	OptionalType = types.NewOptionalType
	// OpaqueType creates an abstract parameterized type with a given name.
	OpaqueType = types.NewOpaqueType
	// ObjectType creates a type references to an externally defined type, e.g. a protobuf message type.
	ObjectType = types.NewObjectType
	// TypeParamType creates a parameterized type instance.
	TypeParamType = types.NewTypeParamType
)
View Source
var (

	// HasMacro expands "has(m.f)" which tests the presence of a field, avoiding the need to
	// specify the field as a string.
	HasMacro = parser.HasMacro

	// AllMacro expands "range.all(var, predicate)" into a comprehension which ensures that all
	// elements in the range satisfy the predicate.
	AllMacro = parser.AllMacro

	// ExistsMacro expands "range.exists(var, predicate)" into a comprehension which ensures that
	// some element in the range satisfies the predicate.
	ExistsMacro = parser.ExistsMacro

	// ExistsOneMacro expands "range.exists_one(var, predicate)", which is true if for exactly one
	// element in range the predicate holds.
	ExistsOneMacro = parser.ExistsOneMacro

	// MapMacro expands "range.map(var, function)" into a comprehension which applies the function
	// to each element in the range to produce a new list.
	MapMacro = parser.MapMacro

	// MapFilterMacro expands "range.map(var, predicate, function)" into a comprehension which
	// first filters the elements in the range by the predicate, then applies the transform function
	// to produce a new list.
	MapFilterMacro = parser.MapFilterMacro

	// FilterMacro expands "range.filter(var, predicate)" into a comprehension which filters
	// elements in the range, producing a new list from the elements that satisfy the predicate.
	FilterMacro = parser.FilterMacro

	// StandardMacros provides an alias to all the CEL macros defined in the standard environment.
	StandardMacros = []Macro{
		HasMacro, AllMacro, ExistsMacro, ExistsOneMacro, MapMacro, MapFilterMacro, FilterMacro,
	}

	// NoMacros provides an alias to an empty list of macros
	NoMacros = []Macro{}
)

Functions

func AstToCheckedExpr

func AstToCheckedExpr(a *Ast) (*exprpb.CheckedExpr, error)

AstToCheckedExpr converts an Ast to an protobuf CheckedExpr value.

If the Ast.IsChecked() returns false, this conversion method will return an error.

func AstToParsedExpr

func AstToParsedExpr(a *Ast) (*exprpb.ParsedExpr, error)

AstToParsedExpr converts an Ast to an protobuf ParsedExpr value.

func AstToString added in v0.3.0

func AstToString(a *Ast) (string, error)

AstToString converts an Ast back to a string if possible.

Note, the conversion may not be an exact replica of the original expression, but will produce a string that is semantically equivalent and whose textual representation is stable.

func AttributePattern added in v0.4.0

func AttributePattern(varName string) *interpreter.AttributePattern

AttributePattern returns an AttributePattern that matches a top-level variable. The pattern is mutable, and its methods support the specification of one or more qualifier patterns.

For example, the AttributePattern(`a`).QualString(`b`) represents a variable access `a` with a string field or index qualification `b`. This pattern will match Attributes `a`, and `a.b`, but not `a.c`.

When using a CEL expression within a container, e.g. a package or namespace, the variable name in the pattern must match the qualified name produced during the variable namespace resolution. For example, when variable `a` is declared within an expression whose container is `ns.app`, the fully qualified variable name may be `ns.app.a`, `ns.a`, or `a` per the CEL namespace resolution rules. Pick the fully qualified variable name that makes sense within the container as the AttributePattern `varName` argument.

See the interpreter.AttributePattern and interpreter.AttributeQualifierPattern for more info about how to create and manipulate AttributePattern values.

func ContextProtoVars added in v0.17.0

func ContextProtoVars(ctx proto.Message) (interpreter.Activation, error)

ContextProtoVars uses the fields of the input proto.Messages as top-level variables within an Activation.

Consider using with `DeclareContextProto` to simplify variable type declarations and publishing when using protocol buffers.

func FormatCELType added in v0.17.0

func FormatCELType(t *Type) string

FormatCELType formats a cel.Type value to a string representation.

The type formatting is identical to FormatType.

func FormatType deprecated added in v0.7.1

func FormatType(t *exprpb.Type) string

FormatType converts a type message into a string representation.

Deprecated: prefer FormatCELType

func NoVars

func NoVars() interpreter.Activation

NoVars returns an empty Activation.

func PartialVars added in v0.4.0

func PartialVars(vars any,
	unknowns ...*interpreter.AttributePattern) (interpreter.PartialActivation, error)

PartialVars returns a PartialActivation which contains variables and a set of AttributePattern values that indicate variables or parts of variables whose value are not yet known.

This method relies on manually configured sets of missing attribute patterns. For a method which infers the missing variables from the input and the configured environment, use Env.PartialVars().

The `vars` value may either be an interpreter.Activation or any valid input to the interpreter.NewActivation call.

func RefValueToValue added in v0.10.0

func RefValueToValue(res ref.Val) (*exprpb.Value, error)

RefValueToValue converts between ref.Val and api.expr.Value. The result Value is the serialized proto form. The ref.Val must not be error or unknown.

func TypeToExprType added in v0.12.0

func TypeToExprType(t *Type) (*exprpb.Type, error)

TypeToExprType converts a CEL-native type representation to a protobuf CEL Type representation.

func ValueToRefValue added in v0.10.0

func ValueToRefValue(adapter types.Adapter, v *exprpb.Value) (ref.Val, error)

ValueToRefValue converts between exprpb.Value and ref.Val.

Types

type ASTOptimizer added in v0.18.0

type ASTOptimizer interface {
	// Optimize optimizes a type-checked AST within an Environment and accumulates any issues.
	Optimize(*OptimizerContext, *ast.AST) *ast.AST
}

ASTOptimizer applies an optimization over an AST and returns the optimized result.

func NewConstantFoldingOptimizer added in v0.18.0

func NewConstantFoldingOptimizer(opts ...ConstantFoldingOption) (ASTOptimizer, error)

NewConstantFoldingOptimizer creates an optimizer which inlines constant scalar an aggregate literal values within function calls and select statements with their evaluated result.

func NewInliningOptimizer added in v0.18.0

func NewInliningOptimizer(inlineVars ...*InlineVariable) ASTOptimizer

NewInliningOptimizer creates and optimizer which replaces variables with expression definitions.

If a variable occurs one time, the variable is replaced by the inline definition. If the variable occurs more than once, the variable occurences are replaced by a cel.bind() call.

type ASTValidator added in v0.17.0

type ASTValidator interface {
	// Name returns the name of the validator. Names must be unique.
	Name() string

	// Validate validates a given Ast within an Environment and collects a set of potential issues.
	//
	// The ValidatorConfig is generated from the set of ASTValidatorConfigurer instances prior to
	// the invocation of the Validate call. The expectation is that the validator configuration
	// is created in sequence and immutable once provided to the Validate call.
	//
	// See individual validators for more information on their configuration keys and configuration
	// properties.
	Validate(*Env, ValidatorConfig, *ast.AST, *Issues)
}

ASTValidator defines a singleton interface for validating a type-checked Ast against an environment.

Note: the Issues argument is mutable in the sense that it is intended to collect errors which will be reported to the caller.

func ValidateComprehensionNestingLimit added in v0.17.0

func ValidateComprehensionNestingLimit(limit int) ASTValidator

ValidateComprehensionNestingLimit ensures that comprehension nesting does not exceed the specified limit.

This validator can be useful for preventing arbitrarily nested comprehensions which can take high polynomial time to complete.

Note, this limit does not apply to comprehensions with an empty iteration range, as these comprehensions have no actual looping cost. The cel.bind() utilizes the comprehension structure to perform local variable assignments and supplies an empty iteration range, so they won't count against the nesting limit either.

func ValidateDurationLiterals added in v0.17.0

func ValidateDurationLiterals() ASTValidator

ValidateDurationLiterals ensures that duration literal arguments are valid immediately after type-check.

func ValidateHomogeneousAggregateLiterals added in v0.17.0

func ValidateHomogeneousAggregateLiterals() ASTValidator

ValidateHomogeneousAggregateLiterals checks that all list and map literals entries have the same types, i.e. no mixed list element types or mixed map key or map value types.

Note: the string format call relies on a mixed element type list for ease of use, so this check skips all literals which occur within string format calls.

func ValidateRegexLiterals added in v0.17.0

func ValidateRegexLiterals() ASTValidator

ValidateRegexLiterals ensures that regex patterns are validated after type-check.

func ValidateTimestampLiterals added in v0.17.0

func ValidateTimestampLiterals() ASTValidator

ValidateTimestampLiterals ensures that timestamp literal arguments are valid immediately after type-check.

type ASTValidatorConfigurer added in v0.17.0

type ASTValidatorConfigurer interface {
	Configure(MutableValidatorConfig) error
}

ASTValidatorConfigurer indicates that this object, currently expected to be an ASTValidator, participates in validator configuration settings.

This interface may be split from the expectation of being an ASTValidator instance in the future.

type Ast

type Ast struct {
	// contains filtered or unexported fields
}

Ast representing the checked or unchecked expression, its source, and related metadata such as source position information.

func CheckedExprToAst

func CheckedExprToAst(checkedExpr *exprpb.CheckedExpr) *Ast

CheckedExprToAst converts a checked expression proto message to an Ast.

func CheckedExprToAstWithSource added in v0.9.0

func CheckedExprToAstWithSource(checkedExpr *exprpb.CheckedExpr, src Source) (*Ast, error)

CheckedExprToAstWithSource converts a checked expression proto message to an Ast, using the provided Source as the textual contents.

In general the source is not necessary unless the AST has been modified between the `Parse` and `Check` calls as an `Ast` created from the `Parse` step will carry the source through future calls.

Prefer CheckedExprToAst if loading expressions from storage.

func ParsedExprToAst

func ParsedExprToAst(parsedExpr *exprpb.ParsedExpr) *Ast

ParsedExprToAst converts a parsed expression proto message to an Ast.

func ParsedExprToAstWithSource added in v0.9.0

func ParsedExprToAstWithSource(parsedExpr *exprpb.ParsedExpr, src Source) *Ast

ParsedExprToAstWithSource converts a parsed expression proto message to an Ast, using the provided Source as the textual contents.

In general you only need this if you need to recheck a previously checked expression, or if you need to separately check a subset of an expression.

Prefer ParsedExprToAst if loading expressions from storage.

func (*Ast) Expr deprecated

func (ast *Ast) Expr() *exprpb.Expr

Expr returns the proto serializable instance of the parsed/checked expression.

Deprecated: prefer cel.AstToCheckedExpr() or cel.AstToParsedExpr() and call GetExpr() the result instead.

func (*Ast) IsChecked

func (ast *Ast) IsChecked() bool

IsChecked returns whether the Ast value has been successfully type-checked.

func (*Ast) NativeRep added in v0.18.2

func (ast *Ast) NativeRep() *celast.AST

NativeRep converts the AST to a Go-native representation.

func (*Ast) OutputType added in v0.12.0

func (ast *Ast) OutputType() *Type

OutputType returns the output type of the expression if the Ast has been type-checked, else returns cel.DynType as the parse step cannot infer types.

func (*Ast) ResultType deprecated

func (ast *Ast) ResultType() *exprpb.Type

ResultType returns the output type of the expression if the Ast has been type-checked, else returns chkdecls.Dyn as the parse step cannot infer the type.

Deprecated: use OutputType

func (*Ast) Source

func (ast *Ast) Source() Source

Source returns a view of the input used to create the Ast. This source may be complete or constructed from the SourceInfo.

func (*Ast) SourceInfo

func (ast *Ast) SourceInfo() *exprpb.SourceInfo

SourceInfo returns character offset and newline position information about expression elements.

type ConstantFoldingOption added in v0.18.0

type ConstantFoldingOption func(opt *constantFoldingOptimizer) (*constantFoldingOptimizer, error)

ConstantFoldingOption defines a functional option for configuring constant folding.

func MaxConstantFoldIterations added in v0.18.0

func MaxConstantFoldIterations(limit int) ConstantFoldingOption

MaxConstantFoldIterations limits the number of times literals may be folding during optimization.

Defaults to 100 if not set.

type Env

type Env struct {
	Container *containers.Container
	// contains filtered or unexported fields
}

Env encapsulates the context necessary to perform parsing, type checking, or generation of evaluable programs for different expressions.

func NewCustomEnv added in v0.4.0

func NewCustomEnv(opts ...EnvOption) (*Env, error)

NewCustomEnv creates a custom program environment which is not automatically configured with the standard library of functions and macros documented in the CEL spec.

The purpose for using a custom environment might be for subsetting the standard library produced by the cel.StdLib() function. Subsetting CEL is a core aspect of its design that allows users to limit the compute and memory impact of a CEL program by controlling the functions and macros that may appear in a given expression.

See the EnvOption helper functions for the options that can be used to configure the environment.

func NewEnv

func NewEnv(opts ...EnvOption) (*Env, error)

NewEnv creates a program environment configured with the standard library of CEL functions and macros. The Env value returned can parse and check any CEL program which builds upon the core features documented in the CEL specification.

See the EnvOption helper functions for the options that can be used to configure the environment.

func (*Env) CELTypeAdapter added in v0.17.0

func (e *Env) CELTypeAdapter() types.Adapter

CELTypeAdapter returns the `types.Adapter` configured for the environment.

func (*Env) CELTypeProvider added in v0.17.0

func (e *Env) CELTypeProvider() types.Provider

CELTypeProvider returns the `types.Provider` configured for the environment.

func (*Env) Check

func (e *Env) Check(ast *Ast) (*Ast, *Issues)

Check performs type-checking on the input Ast and yields a checked Ast and/or set of Issues. If any `ASTValidators` are configured on the environment, they will be applied after a valid type-check result. If any issues are detected, the validators will provide them on the output Issues object.

Either checking or validation has failed if the returned Issues value and its Issues.Err() value are non-nil. Issues should be inspected if they are non-nil, but may not represent a fatal error.

It is possible to have both non-nil Ast and Issues values returned from this call: however, the mere presence of an Ast does not imply that it is valid for use.

func (*Env) Compile added in v0.4.0

func (e *Env) Compile(txt string) (*Ast, *Issues)

Compile combines the Parse and Check phases CEL program compilation to produce an Ast and associated issues.

If an error is encountered during parsing the Compile step will not continue with the Check phase. If non-error issues are encountered during Parse, they may be combined with any issues discovered during Check.

Note, for parse-only uses of CEL use Parse.

func (*Env) CompileSource added in v0.4.0

func (e *Env) CompileSource(src Source) (*Ast, *Issues)

CompileSource combines the Parse and Check phases CEL program compilation to produce an Ast and associated issues.

If an error is encountered during parsing the CompileSource step will not continue with the Check phase. If non-error issues are encountered during Parse, they may be combined with any issues discovered during Check.

Note, for parse-only uses of CEL use Parse.

func (*Env) EstimateCost added in v0.10.0

func (e *Env) EstimateCost(ast *Ast, estimator checker.CostEstimator, opts ...checker.CostOption) (checker.CostEstimate, error)

EstimateCost estimates the cost of a type checked CEL expression using the length estimates of input data and extension functions provided by estimator.

func (*Env) Extend added in v0.3.2

func (e *Env) Extend(opts ...EnvOption) (*Env, error)

Extend the current environment with additional options to produce a new Env.

Note, the extended Env value should not share memory with the original. It is possible, however, that a CustomTypeAdapter or CustomTypeProvider options could provide values which are mutable. To ensure separation of state between extended environments either make sure the TypeAdapter and TypeProvider are immutable, or that their underlying implementations are based on the ref.TypeRegistry which provides a Copy method which will be invoked by this method.

func (*Env) HasFeature added in v0.5.1

func (e *Env) HasFeature(flag int) bool

HasFeature checks whether the environment enables the given feature flag, as enumerated in options.go.

func (*Env) HasLibrary added in v0.13.0

func (e *Env) HasLibrary(libName string) bool

HasLibrary returns whether a specific SingletonLibrary has been configured in the environment.

func (*Env) HasValidator added in v0.17.0

func (e *Env) HasValidator(name string) bool

HasValidator returns whether a specific ASTValidator has been configured in the environment.

func (*Env) Libraries added in v0.17.5

func (e *Env) Libraries() []string

Libraries returns a list of SingletonLibrary that have been configured in the environment.

func (*Env) Parse

func (e *Env) Parse(txt string) (*Ast, *Issues)

Parse parses the input expression value `txt` to a Ast and/or a set of Issues.

This form of Parse creates a Source value for the input `txt` and forwards to the ParseSource method.

func (*Env) ParseSource added in v0.4.0

func (e *Env) ParseSource(src Source) (*Ast, *Issues)

ParseSource parses the input source to an Ast and/or set of Issues.

Parsing has failed if the returned Issues value and its Issues.Err() value is non-nil. Issues should be inspected if they are non-nil, but may not represent a fatal error.

It is possible to have both non-nil Ast and Issues values returned from this call; however, the mere presence of an Ast does not imply that it is valid for use.

func (*Env) PartialVars added in v0.17.0

func (e *Env) PartialVars(vars any) (interpreter.PartialActivation, error)

PartialVars returns an interpreter.PartialActivation where all variables not in the input variable set, but which have been configured in the environment, are marked as unknown.

The `vars` value may either be an interpreter.Activation or any valid input to the interpreter.NewActivation call.

Note, this is equivalent to calling cel.PartialVars and manually configuring the set of unknown variables. For more advanced use cases of partial state where portions of an object graph, rather than top-level variables, are missing the PartialVars() method may be a more suitable choice.

Note, the PartialVars will behave the same as an interpreter.EmptyActivation unless the PartialAttributes option is provided as a ProgramOption.

func (*Env) Program

func (e *Env) Program(ast *Ast, opts ...ProgramOption) (Program, error)

Program generates an evaluable instance of the Ast within the environment (Env).

func (*Env) ResidualAst added in v0.4.0

func (e *Env) ResidualAst(a *Ast, details *EvalDetails) (*Ast, error)

ResidualAst takes an Ast and its EvalDetails to produce a new Ast which only contains the attribute references which are unknown.

Residual expressions are beneficial in a few scenarios:

- Optimizing constant expression evaluations away. - Indexing and pruning expressions based on known input arguments. - Surfacing additional requirements that are needed in order to complete an evaluation. - Sharing the evaluation of an expression across multiple machines/nodes.

For example, if an expression targets a 'resource' and 'request' attribute and the possible values for the resource are known, a PartialActivation could mark the 'request' as an unknown interpreter.AttributePattern and the resulting ResidualAst would be reduced to only the parts of the expression that reference the 'request'.

Note, the expression ids within the residual AST generated through this method have no correlation to the expression ids of the original AST.

See the PartialVars helper for how to construct a PartialActivation.

TODO: Consider adding an option to generate a Program.Residual to avoid round-tripping to an Ast format and then Program again.

func (*Env) TypeAdapter deprecated added in v0.2.0

func (e *Env) TypeAdapter() ref.TypeAdapter

TypeAdapter returns the `ref.TypeAdapter` configured for the environment.

Deprecated: use CELTypeAdapter()

func (*Env) TypeProvider deprecated added in v0.2.0

func (e *Env) TypeProvider() ref.TypeProvider

TypeProvider returns the `ref.TypeProvider` configured for the environment.

Deprecated: use CELTypeProvider()

func (*Env) UnknownVars added in v0.4.0

func (e *Env) UnknownVars() interpreter.PartialActivation

UnknownVars returns an interpreter.PartialActivation which marks all variables declared in the Env as unknown AttributePattern values.

Note, the UnknownVars will behave the same as an interpreter.EmptyActivation unless the PartialAttributes option is provided as a ProgramOption.

type EnvOption

type EnvOption func(e *Env) (*Env, error)

EnvOption is a functional interface for configuring the environment.

func ASTValidators added in v0.17.0

func ASTValidators(validators ...ASTValidator) EnvOption

ASTValidators configures a set of ASTValidator instances into the target environment.

Validators are applied in the order in which the are specified and are treated as singletons. The same ASTValidator with a given name will not be applied more than once.

func Abbrevs added in v0.6.0

func Abbrevs(qualifiedNames ...string) EnvOption

Abbrevs configures a set of simple names as abbreviations for fully-qualified names.

An abbreviation (abbrev for short) is a simple name that expands to a fully-qualified name. Abbreviations can be useful when working with variables, functions, and especially types from multiple namespaces:

// CEL object construction
qual.pkg.version.ObjTypeName{
   field: alt.container.ver.FieldTypeName{value: ...}
}

Only one the qualified names above may be used as the CEL container, so at least one of these references must be a long qualified name within an otherwise short CEL program. Using the following abbreviations, the program becomes much simpler:

// CEL Go option
Abbrevs("qual.pkg.version.ObjTypeName", "alt.container.ver.FieldTypeName")
// Simplified Object construction
ObjTypeName{field: FieldTypeName{value: ...}}

There are a few rules for the qualified names and the simple abbreviations generated from them: - Qualified names must be dot-delimited, e.g. `package.subpkg.name`. - The last element in the qualified name is the abbreviation. - Abbreviations must not collide with each other. - The abbreviation must not collide with unqualified names in use.

Abbreviations are distinct from container-based references in the following important ways: - Abbreviations must expand to a fully-qualified name. - Expanded abbreviations do not participate in namespace resolution. - Abbreviation expansion is done instead of the container search for a matching identifier. - Containers follow C++ namespace resolution rules with searches from the most qualified name

to the least qualified name.

- Container references within the CEL program may be relative, and are resolved to fully

qualified names at either type-check time or program plan time, whichever comes first.

If there is ever a case where an identifier could be in both the container and as an abbreviation, the abbreviation wins as this will ensure that the meaning of a program is preserved between compilations even as the container evolves.

func ClearMacros

func ClearMacros() EnvOption

ClearMacros options clears all parser macros.

Clearing macros will ensure CEL expressions can only contain linear evaluation paths, as comprehensions such as `all` and `exists` are enabled only via macros.

func Constant added in v0.17.0

func Constant(name string, t *Type, v ref.Val) EnvOption

Constant creates an instances of an identifier declaration with a variable name, type, and value.

func Container

func Container(name string) EnvOption

Container sets the container for resolving variable names. Defaults to an empty container.

If all references within an expression are relative to a protocol buffer package, then specifying a container of `google.type` would make it possible to write expressions such as `Expr{expression: 'a < b'}` instead of having to write `google.type.Expr{...}`.

func CostEstimatorOptions added in v0.17.7

func CostEstimatorOptions(costOpts ...checker.CostOption) EnvOption

CostEstimatorOptions configure type-check time options for estimating expression cost.

func CrossTypeNumericComparisons added in v0.10.0

func CrossTypeNumericComparisons(enabled bool) EnvOption

CrossTypeNumericComparisons makes it possible to compare across numeric types, e.g. double < int

func CustomTypeAdapter added in v0.2.0

func CustomTypeAdapter(adapter types.Adapter) EnvOption

CustomTypeAdapter swaps the default types.Adapter implementation with a custom one.

Note: This option must be specified before the Types and TypeDescs options when used together.

func CustomTypeProvider

func CustomTypeProvider(provider any) EnvOption

CustomTypeProvider replaces the types.Provider implementation with a custom one.

The `provider` variable type may either be types.Provider or ref.TypeProvider (deprecated)

Note: This option must be specified before the Types and TypeDescs options when used together.

func Declarations

func Declarations(decls ...*exprpb.Decl) EnvOption

Declarations option extends the declaration set configured in the environment.

Note: Declarations will by default be appended to the pre-existing declaration set configured for the environment. The NewEnv call builds on top of the standard CEL declarations. For a purely custom set of declarations use NewCustomEnv.

func DeclareContextProto added in v0.8.0

func DeclareContextProto(descriptor protoreflect.MessageDescriptor) EnvOption

DeclareContextProto returns an option to extend CEL environment with declarations from the given context proto. Each field of the proto defines a variable of the same name in the environment. https://github.com/google/cel-spec/blob/master/doc/langdef.md#evaluation-environment

func DefaultUTCTimeZone added in v0.12.0

func DefaultUTCTimeZone(enabled bool) EnvOption

DefaultUTCTimeZone ensures that time-based operations use the UTC timezone rather than the input time's local timezone.

func EagerlyValidateDeclarations added in v0.11.1

func EagerlyValidateDeclarations(enabled bool) EnvOption

EagerlyValidateDeclarations ensures that any collisions between configured declarations are caught at the time of the `NewEnv` call.

Eagerly validating declarations is also useful for bootstrapping a base `cel.Env` value. Calls to base `Env.Extend()` will be significantly faster when declarations are eagerly validated as declarations will be collision-checked at most once and only incrementally by way of `Extend`

Disabled by default as not all environments are used for type-checking.

func EnableMacroCallTracking added in v0.10.0

func EnableMacroCallTracking() EnvOption

EnableMacroCallTracking ensures that call expressions which are replaced by macros are tracked in the `SourceInfo` of parsed and checked expressions.

func ExprDeclToDeclaration added in v0.12.0

func ExprDeclToDeclaration(d *exprpb.Decl) (EnvOption, error)

ExprDeclToDeclaration converts a protobuf CEL declaration to a CEL-native declaration, either a Variable or Function.

func ExtendedValidations added in v0.17.0

func ExtendedValidations() EnvOption

ExtendedValidations collects a set of common AST validations which reduce the likelihood of runtime errors.

- Validate duration and timestamp literals - Ensure regex strings are valid - Disable mixed type list and map literals

func Function added in v0.12.0

func Function(name string, opts ...FunctionOpt) EnvOption

Function defines a function and overloads with optional singleton or per-overload bindings.

Using Function is roughly equivalent to calling Declarations() to declare the function signatures and Functions() to define the function bindings, if they have been defined. Specifying the same function name more than once will result in the aggregation of the function overloads. If any signatures conflict between the existing and new function definition an error will be raised. However, if the signatures are identical and the overload ids are the same, the redefinition will be considered a no-op.

One key difference with using Function() is that each FunctionDecl provided will handle dynamic dispatch based on the type-signatures of the overloads provided which means overload resolution at runtime is handled out of the box rather than via a custom binding for overload resolution via Functions():

- Overloads are searched in the order they are declared - Dynamic dispatch for lists and maps is limited by inspection of the list and map contents

at runtime. Empty lists and maps will result in a 'default dispatch'

- In the event that a default dispatch occurs, the first overload provided is the one invoked

If you intend to use overloads which differentiate based on the key or element type of a list or map, consider using a generic function instead: e.g. func(list(T)) or func(map(K, V)) as this will allow your implementation to determine how best to handle dispatch and the default behavior for empty lists and maps whose contents cannot be inspected.

For functions which use parameterized opaque types (abstract types), consider using a singleton function which is capable of inspecting the contents of the type and resolving the appropriate overload as CEL can only make inferences by type-name regarding such types.

func HomogeneousAggregateLiterals added in v0.2.0

func HomogeneousAggregateLiterals() EnvOption

HomogeneousAggregateLiterals disables mixed type list and map literal values.

Note, it is still possible to have heterogeneous aggregates when provided as variables to the expression, as well as via conversion of well-known dynamic types, or with unchecked expressions.

func Lib added in v0.4.0

func Lib(l Library) EnvOption

Lib creates an EnvOption out of a Library, allowing libraries to be provided as functional args, and to be linked to each other.

func Macros

func Macros(macros ...Macro) EnvOption

Macros option extends the macro set configured in the environment.

Note: This option must be specified after ClearMacros if used together.

func OptionalTypes added in v0.13.0

func OptionalTypes(opts ...OptionalTypesOption) EnvOption

OptionalTypes enable support for optional syntax and types in CEL.

The optional value type makes it possible to express whether variables have been provided, whether a result has been computed, and in the future whether an object field path, map key value, or list index has a value.

Syntax Changes

OptionalTypes are unlike other CEL extensions because they modify the CEL syntax itself, notably through the use of a `?` preceding a field name or index value.

## Field Selection

The optional syntax in field selection is denoted as `obj.?field`. In other words, if a field is set, return `optional.of(obj.field)“, else `optional.none()`. The optional field selection is viral in the sense that after the first optional selection all subsequent selections or indices are treated as optional, i.e. the following expressions are equivalent:

obj.?field.subfield
obj.?field.?subfield

## Indexing

Similar to field selection, the optional syntax can be used in index expressions on maps and lists:

list[?0]
map[?key]

## Optional Field Setting

When creating map or message literals, if a field may be optionally set based on its presence, then placing a `?` before the field name or key will ensure the type on the right-hand side must be optional(T) where T is the type of the field or key-value.

The following returns a map with the key expression set only if the subfield is present, otherwise an empty map is created:

{?key: obj.?field.subfield}

## Optional Element Setting

When creating list literals, an element in the list may be optionally added when the element expression is preceded by a `?`:

[a, ?b, ?c] // return a list with either [a], [a, b], [a, b, c], or [a, c]

Optional.Of

Create an optional(T) value of a given value with type T.

optional.of(10)

Optional.OfNonZeroValue

Create an optional(T) value of a given value with type T if it is not a zero-value. A zero-value the default empty value for any given CEL type, including empty protobuf message types. If the value is empty, the result of this call will be optional.none().

optional.ofNonZeroValue([1, 2, 3]) // optional(list(int))
optional.ofNonZeroValue([]) // optional.none()
optional.ofNonZeroValue(0)  // optional.none()
optional.ofNonZeroValue("") // optional.none()

Optional.None

Create an empty optional value.

HasValue

Determine whether the optional contains a value.

optional.of(b'hello').hasValue() // true
optional.ofNonZeroValue({}).hasValue() // false

Value

Get the value contained by the optional. If the optional does not have a value, the result will be a CEL error.

optional.of(b'hello').value() // b'hello'
optional.ofNonZeroValue({}).value() // error

Or

If the value on the left-hand side is optional.none(), the optional value on the right hand side is returned. If the value on the left-hand set is valued, then it is returned. This operation is short-circuiting and will only evaluate as many links in the `or` chain as are needed to return a non-empty optional value.

obj.?field.or(m[?key])
l[?index].or(obj.?field.subfield).or(obj.?other)

OrValue

Either return the value contained within the optional on the left-hand side or return the alternative value on the right hand side.

m[?key].orValue("none")

OptMap

Apply a transformation to the optional's underlying value if it is not empty and return an optional typed result based on the transformation. The transformation expression type must return a type T which is wrapped into an optional.

msg.?elements.optMap(e, e.size()).orValue(0)

OptFlatMap

Introduced in version: 1

Apply a transformation to the optional's underlying value if it is not empty and return the result. The transform expression must return an optional(T) rather than type T. This can be useful when dealing with zero values and conditionally generating an empty or non-empty result in ways which cannot be expressed with `optMap`.

msg.?elements.optFlatMap(e, e[?0]) // return the first element if present.

func ParserExpressionSizeLimit added in v0.16.0

func ParserExpressionSizeLimit(limit int) EnvOption

ParserExpressionSizeLimit adjusts the number of code points the expression parser is allowed to parse. Defaults defined in the parser package.

func ParserRecursionLimit added in v0.13.0

func ParserRecursionLimit(limit int) EnvOption

ParserRecursionLimit adjusts the AST depth the parser will tolerate. Defaults defined in the parser package.

func StdLib added in v0.4.0

func StdLib() EnvOption

StdLib returns an EnvOption for the standard library of CEL functions and macros.

func TypeDescs added in v0.2.0

func TypeDescs(descs ...any) EnvOption

TypeDescs adds type declarations from any protoreflect.FileDescriptor, protoregistry.Files, google.protobuf.FileDescriptorProto or google.protobuf.FileDescriptorSet provided.

Note that messages instantiated from these descriptors will be *dynamicpb.Message values rather than the concrete message type.

TypeDescs are hermetic to a single Env object, but may be copied to other Env values via extension or by re-using the same EnvOption with another NewEnv() call.

func Types

func Types(addTypes ...any) EnvOption

Types adds one or more type declarations to the environment, allowing for construction of type-literals whose definitions are included in the common expression built-in set.

The input types may either be instances of `proto.Message` or `ref.Type`. Any other type provided to this option will result in an error.

Well-known protobuf types within the `google.protobuf.*` package are included in the standard environment by default.

Note: This option must be specified after the CustomTypeProvider option when used together.

func Variable added in v0.12.0

func Variable(name string, t *Type) EnvOption

Variable creates an instance of a variable declaration with a variable name and type.

type Error added in v0.17.0

type Error = common.Error

Error type which references an expression id, a location within source, and a message.

func ExistsMacroExpander added in v0.12.0

func ExistsMacroExpander(meh MacroExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *Error)

ExistsMacroExpander expands the input call arguments into a comprehension that returns true if any of the elements in the range match the predicate expressions: <iterRange>.exists(<iterVar>, <predicate>)

func ExistsOneMacroExpander added in v0.12.0

func ExistsOneMacroExpander(meh MacroExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *Error)

ExistsOneMacroExpander expands the input call arguments into a comprehension that returns true if exactly one of the elements in the range match the predicate expressions: <iterRange>.exists_one(<iterVar>, <predicate>)

func FilterMacroExpander added in v0.12.0

func FilterMacroExpander(meh MacroExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *Error)

FilterMacroExpander expands the input call arguments into a comprehension which produces a list which contains only elements which match the provided predicate expression: <iterRange>.filter(<iterVar>, <predicate>)

func HasMacroExpander added in v0.12.0

func HasMacroExpander(meh MacroExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *Error)

HasMacroExpander expands the input call arguments into a presence test, e.g. has(<operand>.field)

func MapMacroExpander added in v0.12.0

func MapMacroExpander(meh MacroExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *Error)

MapMacroExpander expands the input call arguments into a comprehension that transforms each element in the input to produce an output list.

There are two call patterns supported by map:

<iterRange>.map(<iterVar>, <transform>)
<iterRange>.map(<iterVar>, <predicate>, <transform>)

In the second form only iterVar values which return true when provided to the predicate expression are transformed.

type EvalDetails

type EvalDetails struct {
	// contains filtered or unexported fields
}

EvalDetails holds additional information observed during the Eval() call.

func (*EvalDetails) ActualCost added in v0.10.0

func (ed *EvalDetails) ActualCost() *uint64

ActualCost returns the tracked cost through the course of execution when `CostTracking` is enabled. Otherwise, returns nil if the cost was not enabled.

func (*EvalDetails) State

func (ed *EvalDetails) State() interpreter.EvalState

State of the evaluation, non-nil if the OptTrackState or OptExhaustiveEval is specified within EvalOptions.

type EvalOption

type EvalOption int

EvalOption indicates an evaluation option that may affect the evaluation behavior or information in the output result.

const (
	// OptTrackState will cause the runtime to return an immutable EvalState value in the Result.
	OptTrackState EvalOption = 1 << iota

	// OptExhaustiveEval causes the runtime to disable short-circuits and track state.
	OptExhaustiveEval EvalOption = 1<<iota | OptTrackState

	// OptOptimize precomputes functions and operators with constants as arguments at program
	// creation time. It also pre-compiles regex pattern constants passed to 'matches', reports any compilation errors
	// at program creation and uses the compiled regex pattern for all 'matches' function invocations.
	// This flag is useful when the expression will be evaluated repeatedly against
	// a series of different inputs.
	OptOptimize EvalOption = 1 << iota

	// OptPartialEval enables the evaluation of a partial state where the input data that may be
	// known to be missing, either as top-level variables, or somewhere within a variable's object
	// member graph.
	//
	// By itself, OptPartialEval does not change evaluation behavior unless the input to the
	// Program Eval() call is created via PartialVars().
	OptPartialEval EvalOption = 1 << iota

	// OptTrackCost enables the runtime cost calculation while validation and return cost within evalDetails
	// cost calculation is available via func ActualCost()
	OptTrackCost EvalOption = 1 << iota

	// OptCheckStringFormat enables compile-time checking of string.format calls for syntax/cardinality.
	//
	// Deprecated: use ext.StringsValidateFormatCalls() as this option is now a no-op.
	OptCheckStringFormat EvalOption = 1 << iota
)

type FunctionOpt added in v0.12.0

type FunctionOpt = decls.FunctionOpt

FunctionOpt defines a functional option for configuring a function declaration.

func DisableDeclaration added in v0.17.0

func DisableDeclaration(value bool) FunctionOpt

DisableDeclaration disables the function signatures, effectively removing them from the type-check environment while preserving the runtime bindings.

func MemberOverload added in v0.12.0

func MemberOverload(overloadID string, args []*Type, resultType *Type, opts ...OverloadOpt) FunctionOpt

MemberOverload defines a new receiver-style overload (or member function) with an overload id, argument types, and result type. Through the use of OverloadOpt options, the overload may also be configured with a binding, an operand trait, and to be non-strict.

Note: function bindings should be commonly configured with Overload instances whereas operand traits and strict-ness should be rare occurrences.

func Overload added in v0.12.0

func Overload(overloadID string, args []*Type, resultType *Type, opts ...OverloadOpt) FunctionOpt

Overload defines a new global overload with an overload id, argument types, and result type. Through the use of OverloadOpt options, the overload may also be configured with a binding, an operand trait, and to be non-strict.

Note: function bindings should be commonly configured with Overload instances whereas operand traits and strict-ness should be rare occurrences.

func SingletonBinaryBinding added in v0.13.0

func SingletonBinaryBinding(fn functions.BinaryOp, traits ...int) FunctionOpt

SingletonBinaryBinding creates a singleton function definition to be used with all function overloads.

Note, this approach works well if operand is expected to have a specific trait which it implements, e.g. traits.ContainerType. Otherwise, prefer per-overload function bindings.

func SingletonBinaryImpl deprecated added in v0.12.0

func SingletonBinaryImpl(fn functions.BinaryOp, traits ...int) FunctionOpt

SingletonBinaryImpl creates a singleton function definition to be used with all function overloads.

Note, this approach works well if operand is expected to have a specific trait which it implements, e.g. traits.ContainerType. Otherwise, prefer per-overload function bindings.

Deprecated: use SingletonBinaryBinding

func SingletonFunctionBinding added in v0.13.0

func SingletonFunctionBinding(fn functions.FunctionOp, traits ...int) FunctionOpt

SingletonFunctionBinding creates a singleton function definition to be used with all function overloads.

Note, this approach works well if operand is expected to have a specific trait which it implements, e.g. traits.ContainerType. Otherwise, prefer per-overload function bindings.

func SingletonFunctionImpl deprecated added in v0.12.0

func SingletonFunctionImpl(fn functions.FunctionOp, traits ...int) FunctionOpt

SingletonFunctionImpl creates a singleton function definition to be used with all function overloads.

Note, this approach works well if operand is expected to have a specific trait which it implements, e.g. traits.ContainerType. Otherwise, prefer per-overload function bindings.

Deprecated: use SingletonFunctionBinding

func SingletonUnaryBinding added in v0.12.0

func SingletonUnaryBinding(fn functions.UnaryOp, traits ...int) FunctionOpt

SingletonUnaryBinding creates a singleton function definition to be used for all function overloads.

Note, this approach works well if operand is expected to have a specific trait which it implements, e.g. traits.ContainerType. Otherwise, prefer per-overload function bindings.

type InlineVariable added in v0.18.0

type InlineVariable struct {
	// contains filtered or unexported fields
}

InlineVariable holds a variable name to be matched and an AST representing the expression graph which should be used to replace it.

func NewInlineVariable added in v0.18.0

func NewInlineVariable(name string, definition *Ast) *InlineVariable

NewInlineVariable declares a variable name to be replaced by a checked expression.

func NewInlineVariableWithAlias added in v0.18.0

func NewInlineVariableWithAlias(name, alias string, definition *Ast) *InlineVariable

NewInlineVariableWithAlias declares a variable name to be replaced by a checked expression. If the variable occurs more than once, the provided alias will be used to replace the expressions where the variable name occurs.

func (*InlineVariable) Alias added in v0.18.0

func (v *InlineVariable) Alias() string

Alias returns the alias to use when performing cel.bind() calls during inlining.

func (*InlineVariable) Expr added in v0.18.0

func (v *InlineVariable) Expr() ast.Expr

Expr returns the inlined expression value.

func (*InlineVariable) Name added in v0.18.0

func (v *InlineVariable) Name() string

Name returns the qualified variable or field selection to replace.

func (*InlineVariable) Type added in v0.18.0

func (v *InlineVariable) Type() *Type

Type indicates the inlined expression type.

type Issues

type Issues struct {
	// contains filtered or unexported fields
}

Issues defines methods for inspecting the error details of parse and check calls.

Note: in the future, non-fatal warnings and notices may be inspectable via the Issues struct.

func NewIssues added in v0.4.0

func NewIssues(errs *common.Errors) *Issues

NewIssues returns an Issues struct from a common.Errors object.

func NewIssuesWithSourceInfo added in v0.17.0

func NewIssuesWithSourceInfo(errs *common.Errors, info *celast.SourceInfo) *Issues

NewIssuesWithSourceInfo returns an Issues struct from a common.Errors object with SourceInfo metatata which can be used with the `ReportErrorAtID` method for additional error reports within the context information that's inferred from an expression id.

func (*Issues) Append added in v0.4.0

func (i *Issues) Append(other *Issues) *Issues

Append collects the issues from another Issues struct into a new Issues object.

func (*Issues) Err

func (i *Issues) Err() error

Err returns an error value if the issues list contains one or more errors.

func (*Issues) Errors

func (i *Issues) Errors() []*Error

Errors returns the collection of errors encountered in more granular detail.

func (*Issues) ReportErrorAtID added in v0.17.0

func (i *Issues) ReportErrorAtID(id int64, message string, args ...any)

ReportErrorAtID reports an error message with an optional set of formatting arguments.

The source metadata for the expression at `id`, if present, is attached to the error report. To ensure that source metadata is attached to error reports, use NewIssuesWithSourceInfo.

func (*Issues) String added in v0.4.0

func (i *Issues) String() string

String converts the issues to a suitable display string.

type Kind added in v0.12.0

type Kind = types.Kind

Kind indicates a CEL type's kind which is used to differentiate quickly between simple and complex types.

type Library added in v0.4.0

type Library interface {
	// CompileOptions returns a collection of functional options for configuring the Parse / Check
	// environment.
	CompileOptions() []EnvOption

	// ProgramOptions returns a collection of functional options which should be included in every
	// Program generated from the Env.Program() call.
	ProgramOptions() []ProgramOption
}

Library provides a collection of EnvOption and ProgramOption values used to configure a CEL environment for a particular use case or with a related set of functionality.

Note, the ProgramOption values provided by a library are expected to be static and not vary between calls to Env.Program(). If there is a need for such dynamic configuration, prefer to configure these options outside the Library and within the Env.Program() call directly.

type Macro added in v0.12.0

type Macro = parser.Macro

Macro describes a function signature to match and the MacroExpander to apply.

Note: when a Macro should apply to multiple overloads (based on arg count) of a given function, a Macro should be created per arg-count or as a var arg macro.

func GlobalMacro added in v0.17.2

func GlobalMacro(function string, argCount int, factory MacroFactory) Macro

GlobalMacro creates a Macro for a global function with the specified arg count.

func GlobalVarArgMacro added in v0.17.2

func GlobalVarArgMacro(function string, factory MacroFactory) Macro

GlobalVarArgMacro creates a Macro for a global function with a variable arg count.

func NewGlobalMacro deprecated added in v0.12.0

func NewGlobalMacro(function string, argCount int, expander MacroExpander) Macro

NewGlobalMacro creates a Macro for a global function with the specified arg count.

Deprecated: use GlobalMacro

func NewGlobalVarArgMacro deprecated added in v0.12.0

func NewGlobalVarArgMacro(function string, expander MacroExpander) Macro

NewGlobalVarArgMacro creates a Macro for a global function with a variable arg count.

Deprecated: use GlobalVarArgMacro

func NewReceiverMacro deprecated added in v0.12.0

func NewReceiverMacro(function string, argCount int, expander MacroExpander) Macro

NewReceiverMacro creates a Macro for a receiver function matching the specified arg count.

Deprecated: use ReceiverMacro

func NewReceiverVarArgMacro deprecated added in v0.12.0

func NewReceiverVarArgMacro(function string, expander MacroExpander) Macro

NewReceiverVarArgMacro creates a Macro for a receiver function matching a variable arg count.

Deprecated: use ReceiverVarArgMacro

func ReceiverMacro added in v0.17.2

func ReceiverMacro(function string, argCount int, factory MacroFactory) Macro

ReceiverMacro creates a Macro for a receiver function matching the specified arg count.

func ReceiverVarArgMacro added in v0.17.2

func ReceiverVarArgMacro(function string, factory MacroFactory) Macro

ReceiverVarArgMacro creates a Macro for a receiver function matching a variable arg count.

type MacroExpander added in v0.12.0

type MacroExpander func(eh MacroExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *Error)

MacroExpander converts a call and its associated arguments into a protobuf Expr representation.

If the MacroExpander determines within the implementation that an expansion is not needed it may return a nil Expr value to indicate a non-match. However, if an expansion is to be performed, but the arguments are not well-formed, the result of the expansion will be an error.

The MacroExpander accepts as arguments a MacroExprHelper as well as the arguments used in the function call and produces as output an Expr ast node.

Note: when the Macro.IsReceiverStyle() method returns true, the target argument will be nil.

type MacroExprFactory added in v0.17.2

type MacroExprFactory = parser.ExprHelper

MacroExprFactory assists with the creation of Expr values in a manner which is consistent the internal semantics and id generation behaviors of the parser and checker libraries.

type MacroExprHelper added in v0.12.0

type MacroExprHelper interface {
	// Copy the input expression with a brand new set of identifiers.
	Copy(*exprpb.Expr) *exprpb.Expr

	// LiteralBool creates an Expr value for a bool literal.
	LiteralBool(value bool) *exprpb.Expr

	// LiteralBytes creates an Expr value for a byte literal.
	LiteralBytes(value []byte) *exprpb.Expr

	// LiteralDouble creates an Expr value for double literal.
	LiteralDouble(value float64) *exprpb.Expr

	// LiteralInt creates an Expr value for an int literal.
	LiteralInt(value int64) *exprpb.Expr

	// LiteralString creates am Expr value for a string literal.
	LiteralString(value string) *exprpb.Expr

	// LiteralUint creates an Expr value for a uint literal.
	LiteralUint(value uint64) *exprpb.Expr

	// NewList creates a CreateList instruction where the list is comprised of the optional set
	// of elements provided as arguments.
	NewList(elems ...*exprpb.Expr) *exprpb.Expr

	// NewMap creates a CreateStruct instruction for a map where the map is comprised of the
	// optional set of key, value entries.
	NewMap(entries ...*exprpb.Expr_CreateStruct_Entry) *exprpb.Expr

	// NewMapEntry creates a Map Entry for the key, value pair.
	NewMapEntry(key *exprpb.Expr, val *exprpb.Expr, optional bool) *exprpb.Expr_CreateStruct_Entry

	// NewObject creates a CreateStruct instruction for an object with a given type name and
	// optional set of field initializers.
	NewObject(typeName string, fieldInits ...*exprpb.Expr_CreateStruct_Entry) *exprpb.Expr

	// NewObjectFieldInit creates a new Object field initializer from the field name and value.
	NewObjectFieldInit(field string, init *exprpb.Expr, optional bool) *exprpb.Expr_CreateStruct_Entry

	// Fold creates a fold comprehension instruction.
	//
	// - iterVar is the iteration variable name.
	// - iterRange represents the expression that resolves to a list or map where the elements or
	//   keys (respectively) will be iterated over.
	// - accuVar is the accumulation variable name, typically parser.AccumulatorName.
	// - accuInit is the initial expression whose value will be set for the accuVar prior to
	//   folding.
	// - condition is the expression to test to determine whether to continue folding.
	// - step is the expression to evaluation at the conclusion of a single fold iteration.
	// - result is the computation to evaluate at the conclusion of the fold.
	//
	// The accuVar should not shadow variable names that you would like to reference within the
	// environment in the step and condition expressions. Presently, the name __result__ is commonly
	// used by built-in macros but this may change in the future.
	Fold(iterVar string,
		iterRange *exprpb.Expr,
		accuVar string,
		accuInit *exprpb.Expr,
		condition *exprpb.Expr,
		step *exprpb.Expr,
		result *exprpb.Expr) *exprpb.Expr

	// Ident creates an identifier Expr value.
	Ident(name string) *exprpb.Expr

	// AccuIdent returns an accumulator identifier for use with comprehension results.
	AccuIdent() *exprpb.Expr

	// GlobalCall creates a function call Expr value for a global (free) function.
	GlobalCall(function string, args ...*exprpb.Expr) *exprpb.Expr

	// ReceiverCall creates a function call Expr value for a receiver-style function.
	ReceiverCall(function string, target *exprpb.Expr, args ...*exprpb.Expr) *exprpb.Expr

	// PresenceTest creates a Select TestOnly Expr value for modelling has() semantics.
	PresenceTest(operand *exprpb.Expr, field string) *exprpb.Expr

	// Select create a field traversal Expr value.
	Select(operand *exprpb.Expr, field string) *exprpb.Expr

	// OffsetLocation returns the Location of the expression identifier.
	OffsetLocation(exprID int64) common.Location

	// NewError associates an error message with a given expression id.
	NewError(exprID int64, message string) *Error
}

MacroExprHelper exposes helper methods for creating new expressions within a CEL abstract syntax tree. ExprHelper assists with the manipulation of proto-based Expr values in a manner which is consistent with the source position and expression id generation code leveraged by both the parser and type-checker.

type MacroFactory added in v0.17.2

type MacroFactory = parser.MacroExpander

MacroFactory defines an expansion function which converts a call and its arguments to a cel.Expr value.

type MutableValidatorConfig added in v0.17.0

type MutableValidatorConfig interface {
	ValidatorConfig
	Set(name string, value any) error
}

MutableValidatorConfig provides mutation methods for querying and updating validator configuration settings.

type OptimizerContext added in v0.18.0

type OptimizerContext struct {
	*Env

	*Issues
	// contains filtered or unexported fields
}

OptimizerContext embeds Env and Issues instances to make it easy to type-check and evaluate subexpressions and report any errors encountered along the way. The context also embeds the optimizerExprFactory which can be used to generate new sub-expressions with expression ids consistent with the expectations of a parsed expression.

func (OptimizerContext) ClearMacroCall added in v0.20.1

func (opt OptimizerContext) ClearMacroCall(id int64)

ClearMacroCall clears the macro at the given expression id.

func (OptimizerContext) CopyAST added in v0.18.2

func (opt OptimizerContext) CopyAST(a *ast.AST) (ast.Expr, *ast.SourceInfo)

CopyAST creates a renumbered copy of `Expr` and `SourceInfo` values of the input AST, where the renumbering uses the same scheme as the core optimizer logic ensuring there are no collisions between copies.

Use this method before attempting to merge the expression from AST into another.

func (OptimizerContext) CopyASTAndMetadata added in v0.20.1

func (opt OptimizerContext) CopyASTAndMetadata(a *ast.AST) ast.Expr

CopyASTAndMetadata copies the input AST and propagates the macro metadata into the AST being optimized.

func (OptimizerContext) NewAST added in v0.20.1

func (opt OptimizerContext) NewAST(expr ast.Expr) *ast.AST

NewAST creates an AST from the current expression using the tracked source info which is modified and managed by the OptimizerContext.

func (OptimizerContext) NewBindMacro added in v0.18.0

func (opt OptimizerContext) NewBindMacro(macroID int64, varName string, varInit, remaining ast.Expr) (astExpr, macroExpr ast.Expr)

NewBindMacro creates an AST expression representing the expanded bind() macro, and a macro expression representing the unexpanded call signature to be inserted into the source info macro call metadata.

func (OptimizerContext) NewCall added in v0.18.0

func (opt OptimizerContext) NewCall(function string, args ...ast.Expr) ast.Expr

NewCall creates a global function call invocation expression.

Example:

countByField(list, fieldName) - function: countByField - args: [list, fieldName]

func (OptimizerContext) NewHasMacro added in v0.18.2

func (opt OptimizerContext) NewHasMacro(macroID int64, s ast.Expr) (astExpr, macroExpr ast.Expr)

NewHasMacro generates a test-only select expression to be included within an AST and an unexpanded has() macro call signature to be inserted into the source info macro call metadata.

func (OptimizerContext) NewIdent added in v0.18.0

func (opt OptimizerContext) NewIdent(name string) ast.Expr

NewIdent creates a new identifier expression.

Examples:

- simple_var_name - qualified.subpackage.var_name

func (OptimizerContext) NewList added in v0.18.0

func (opt OptimizerContext) NewList(elems []ast.Expr, optIndices []int32) ast.Expr

NewList creates a list expression with a set of optional indices.

Examples:

[a, b] - elems: [a, b] - optIndices: []

[a, ?b, ?c] - elems: [a, b, c] - optIndices: [1, 2]

func (OptimizerContext) NewLiteral added in v0.18.0

func (opt OptimizerContext) NewLiteral(value ref.Val) ast.Expr

NewLiteral creates a new literal expression value.

The range of valid values for a literal generated during optimization is different than for expressions generated via parsing / type-checking, as the ref.Val may be _any_ CEL value so long as the value can be converted back to a literal-like form.

func (OptimizerContext) NewMap added in v0.18.0

func (opt OptimizerContext) NewMap(entries []ast.EntryExpr) ast.Expr

NewMap creates a map from a set of entry expressions which contain a key and value expression.

func (OptimizerContext) NewMapEntry added in v0.18.0

func (opt OptimizerContext) NewMapEntry(key, value ast.Expr, isOptional bool) ast.EntryExpr

NewMapEntry creates a map entry with a key and value expression and a flag to indicate whether the entry is optional.

Examples:

{a: b} - key: a - value: b - optional: false

{?a: ?b} - key: a - value: b - optional: true

func (OptimizerContext) NewMemberCall added in v0.18.0

func (opt OptimizerContext) NewMemberCall(function string, target ast.Expr, args ...ast.Expr) ast.Expr

NewMemberCall creates a member function call invocation expression where 'target' is the receiver of the call.

Example:

list.countByField(fieldName) - function: countByField - target: list - args: [fieldName]

func (OptimizerContext) NewSelect added in v0.18.0

func (opt OptimizerContext) NewSelect(operand ast.Expr, field string) ast.Expr

NewSelect creates a select expression where a field value is selected from an operand.

Example:

msg.field_name - operand: msg - field: field_name

func (OptimizerContext) NewStruct added in v0.18.0

func (opt OptimizerContext) NewStruct(typeName string, fields []ast.EntryExpr) ast.Expr

NewStruct creates a new typed struct value with an set of field initializations.

Example:

pkg.TypeName{field: value} - typeName: pkg.TypeName - fields: [{field: value}]

func (OptimizerContext) NewStructField added in v0.18.0

func (opt OptimizerContext) NewStructField(field string, value ast.Expr, isOptional bool) ast.EntryExpr

NewStructField creates a struct field initialization.

Examples:

{count: 3u} - field: count - value: 3u - optional: false

{?count: x} - field: count - value: x - optional: true

func (OptimizerContext) SetMacroCall added in v0.20.1

func (opt OptimizerContext) SetMacroCall(id int64, expr ast.Expr)

SetMacroCall sets the macro call metadata for the given macro id within the tracked source info metadata.

func (OptimizerContext) UpdateExpr added in v0.18.2

func (opt OptimizerContext) UpdateExpr(target, updated ast.Expr)

UpdateExpr updates the target expression with the updated content while preserving macro metadata.

There are four scenarios during the update to consider: 1. target is not macro, updated is not macro 2. target is macro, updated is not macro 3. target is macro, updated is macro 4. target is not macro, updated is macro

When the target is a macro already, it may either be updated to a new macro function body if the update is also a macro, or it may be removed altogether if the update is a macro.

When the update is a macro, then the target references within other macros must be updated to point to the new updated macro. Otherwise, other macros which pointed to the target body must be replaced with copies of the updated expression body.

type OptionalTypesOption added in v0.17.0

type OptionalTypesOption func(*optionalLib) *optionalLib

OptionalTypesOption is a functional interface for configuring the strings library.

func OptionalTypesVersion added in v0.17.0

func OptionalTypesVersion(version uint32) OptionalTypesOption

OptionalTypesVersion configures the version of the optional type library.

The version limits which functions are available. Only functions introduced below or equal to the given version included in the library. If this option is not set, all functions are available.

See the library documentation to determine which version a function was introduced. If the documentation does not state which version a function was introduced, it can be assumed to be introduced at version 0, when the library was first created.

type OverloadOpt added in v0.12.0

type OverloadOpt = decls.OverloadOpt

OverloadOpt is a functional option for configuring a function overload.

func BinaryBinding added in v0.12.0

func BinaryBinding(binding functions.BinaryOp) OverloadOpt

BinaryBinding provides the implementation of a binary overload. The provided function is protected by a runtime type-guard which ensures runtime type agreement between the overload signature and runtime argument types.

func FunctionBinding added in v0.12.0

func FunctionBinding(binding functions.FunctionOp) OverloadOpt

FunctionBinding provides the implementation of a variadic overload. The provided function is protected by a runtime type-guard which ensures runtime type agreement between the overload signature and runtime argument types.

func OverloadIsNonStrict added in v0.12.0

func OverloadIsNonStrict() OverloadOpt

OverloadIsNonStrict enables the function to be called with error and unknown argument values.

Note: do not use this option unless absoluately necessary as it should be an uncommon feature.

func OverloadOperandTrait added in v0.12.0

func OverloadOperandTrait(trait int) OverloadOpt

OverloadOperandTrait configures a set of traits which the first argument to the overload must implement in order to be successfully invoked.

func UnaryBinding added in v0.12.0

func UnaryBinding(binding functions.UnaryOp) OverloadOpt

UnaryBinding provides the implementation of a unary overload. The provided function is protected by a runtime type-guard which ensures runtime type agreement between the overload signature and runtime argument types.

type Program

type Program interface {
	// Eval returns the result of an evaluation of the Ast and environment against the input vars.
	//
	// The vars value may either be an `interpreter.Activation` or a `map[string]any`.
	//
	// If the `OptTrackState`, `OptTrackCost` or `OptExhaustiveEval` flags are used, the `details` response will
	// be non-nil. Given this caveat on `details`, the return state from evaluation will be:
	//
	// *  `val`, `details`, `nil` - Successful evaluation of a non-error result.
	// *  `val`, `details`, `err` - Successful evaluation to an error result.
	// *  `nil`, `details`, `err` - Unsuccessful evaluation.
	//
	// An unsuccessful evaluation is typically the result of a series of incompatible `EnvOption`
	// or `ProgramOption` values used in the creation of the evaluation environment or executable
	// program.
	Eval(any) (ref.Val, *EvalDetails, error)

	// ContextEval evaluates the program with a set of input variables and a context object in order
	// to support cancellation and timeouts. This method must be used in conjunction with the
	// InterruptCheckFrequency() option for cancellation interrupts to be impact evaluation.
	//
	// The vars value may either be an `interpreter.Activation` or `map[string]any`.
	//
	// The output contract for `ContextEval` is otherwise identical to the `Eval` method.
	ContextEval(context.Context, any) (ref.Val, *EvalDetails, error)
}

Program is an evaluable view of an Ast.

type ProgramOption

type ProgramOption func(p *prog) (*prog, error)

ProgramOption is a functional interface for configuring evaluation bindings and behaviors.

func CostLimit added in v0.10.0

func CostLimit(costLimit uint64) ProgramOption

CostLimit enables cost tracking and sets configures program evaluation to exit early with a "runtime cost limit exceeded" error if the runtime cost exceeds the costLimit. The CostLimit is a metric that corresponds to the number and estimated expense of operations performed while evaluating an expression. It is indicative of CPU usage, not memory usage.

func CostTrackerOptions added in v0.17.7

func CostTrackerOptions(costOpts ...interpreter.CostTrackerOption) ProgramOption

CostTrackerOptions configures a set of options for cost-tracking.

Note, CostTrackerOptions is a no-op unless CostTracking is also enabled.

func CostTracking added in v0.10.0

func CostTracking(costEstimator interpreter.ActualCostEstimator) ProgramOption

CostTracking enables cost tracking and registers a ActualCostEstimator that can optionally provide a runtime cost estimate for any function calls.

func CustomDecorator added in v0.6.0

CustomDecorator appends an InterpreterDecorator to the program.

InterpretableDecorators can be used to inspect, alter, or replace the Program plan.

func EvalOptions

func EvalOptions(opts ...EvalOption) ProgramOption

EvalOptions sets one or more evaluation options which may affect the evaluation or Result.

func Functions deprecated

func Functions(funcs ...*functions.Overload) ProgramOption

Functions adds function overloads that extend or override the set of CEL built-ins.

Deprecated: use Function() instead to declare the function, its overload signatures, and the overload implementations.

func Globals

func Globals(vars any) ProgramOption

Globals sets the global variable values for a given program. These values may be shadowed by variables with the same name provided to the Eval() call. If Globals is used in a Library with a Lib EnvOption, vars may shadow variables provided by previously added libraries.

The vars value may either be an `interpreter.Activation` instance or a `map[string]any`.

func InterruptCheckFrequency added in v0.10.0

func InterruptCheckFrequency(checkFrequency uint) ProgramOption

InterruptCheckFrequency configures the number of iterations within a comprehension to evaluate before checking whether the function evaluation has been interrupted.

func OptimizeRegex added in v0.10.0

func OptimizeRegex(regexOptimizations ...*interpreter.RegexOptimization) ProgramOption

OptimizeRegex provides a way to replace the InterpretableCall for regex functions. This can be used to compile regex string constants at program creation time and report any errors and then use the compiled regex for all regex function invocations.

type SingletonLibrary added in v0.13.0

type SingletonLibrary interface {
	Library

	// LibraryName provides a namespaced name which is used to check whether the library has already
	// been configured in the environment.
	LibraryName() string
}

SingletonLibrary refines the Library interface to ensure that libraries in this format are only configured once within the environment.

type Source

type Source = common.Source

Source interface representing a user-provided expression.

type StaticOptimizer added in v0.18.0

type StaticOptimizer struct {
	// contains filtered or unexported fields
}

StaticOptimizer contains a sequence of ASTOptimizer instances which will be applied in order.

The static optimizer normalizes expression ids and type-checking run between optimization passes to ensure that the final optimized output is a valid expression with metadata consistent with what would have been generated from a parsed and checked expression.

Note: source position information is best-effort and likely wrong, but optimized expressions should be suitable for calls to parser.Unparse.

func NewStaticOptimizer added in v0.18.0

func NewStaticOptimizer(optimizers ...ASTOptimizer) *StaticOptimizer

NewStaticOptimizer creates a StaticOptimizer with a sequence of ASTOptimizer's to be applied to a checked expression.

func (*StaticOptimizer) Optimize added in v0.18.0

func (opt *StaticOptimizer) Optimize(env *Env, a *Ast) (*Ast, *Issues)

Optimize applies a sequence of optimizations to an Ast within a given environment.

If issues are encountered, the Issues.Err() return value will be non-nil.

type Type added in v0.12.0

type Type = types.Type

Type holds a reference to a runtime type with an optional type-checked set of type parameters.

func ExprTypeToType added in v0.12.0

func ExprTypeToType(t *exprpb.Type) (*Type, error)

ExprTypeToType converts a protobuf CEL type representation to a CEL-native type representation.

type ValidatorConfig added in v0.17.0

type ValidatorConfig interface {
	GetOrDefault(name string, value any) any
}

ValidatorConfig provides an accessor method for querying validator configuration state.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL