cel

package
v0.6.0 Latest Latest
Warning

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

Go to latest
Published: Dec 25, 2019 License: Apache-2.0 Imports: 14 Imported by: 0

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
// 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.
decls := Declarations(
	// Identifiers used within this expression.
	decls.NewIdent("i", decls.String, nil),
	decls.NewIdent("you", decls.String, nil),
	// Function to generate a greeting from one person to another.
	//    i.greet(you)
	decls.NewFunction("greet",
		decls.NewInstanceOverload("string_greet_string",
			[]*exprpb.Type{decls.String, decls.String},
			decls.String)))
e, err := NewEnv(decls)
if err != nil {
	log.Fatalf("environment creation error: %s\n", err)
}

// Parse and check the expression.
p, iss := e.Parse("i.greet(you)")
if iss != nil && iss.Err() != nil {
	log.Fatalln(iss.Err())
}
c, iss := e.Check(p)
if iss != nil && iss.Err() != nil {
	log.Fatalln(iss.Err())
}

// Create the program.
funcs := Functions(
	&functions.Overload{
		Operator: "string_greet_string",
		Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
			return types.String(
				fmt.Sprintf("Hello %s! Nice to meet you, I'm %s.\n", rhs, lhs))
		}})
prg, err := e.Program(c, funcs)
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]interface{}{
	// 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)

ExampleGlobalOverload 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.
decls := Declarations(
	// Identifiers used within this expression.
	decls.NewIdent("i", decls.String, nil),
	decls.NewIdent("you", decls.String, nil),
	// Function to generate shake_hands between two people.
	//    shake_hands(i,you)
	decls.NewFunction("shake_hands",
		decls.NewOverload("shake_hands_string_string",
			[]*exprpb.Type{decls.String, decls.String},
			decls.String)))
e, err := NewEnv(decls)
if err != nil {
	log.Fatalf("environment creation error: %s\n", err)
}

// Parse and check the expression.
p, iss := e.Parse(`shake_hands(i,you)`)
if iss != nil && iss.Err() != nil {
	log.Fatalln(iss.Err())
}
c, iss := e.Check(p)
if iss != nil && iss.Err() != nil {
	log.Fatalln(iss.Err())
}

// Create the program.
funcs := Functions(
	&functions.Overload{
		Operator: "shake_hands_string_string",
		Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
			s1, ok := lhs.(types.String)
			if !ok {
				return types.ValOrErr(lhs, "unexpected type '%v' passed to shake_hands", lhs.Type())
			}
			s2, ok := rhs.(types.String)
			if !ok {
				return types.ValOrErr(rhs, "unexpected type '%v' passed to shake_hands", rhs.Type())
			}
			return types.String(
				fmt.Sprintf("%s and %s are shaking hands.\n", s1, s2))
		}})
prg, err := e.Program(c, funcs)
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]interface{}{
	"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.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

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

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.

func NoVars

func NoVars() interpreter.Activation

NoVars returns an empty Activation.

Types

type Ast

type Ast interface {
	// Expr returns the proto serializable instance of the parsed/checked expression.
	Expr() *exprpb.Expr

	// IsChecked returns whether the Ast value has been successfully type-checked.
	IsChecked() bool

	// ResultType returns the output type of the expression if the Ast has been type-checked,
	// else returns decls.Dyn as the parse step cannot infer the type.
	ResultType() *exprpb.Type

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

	// SourceInfo returns character offset and newling position information about expression
	// elements.
	SourceInfo() *exprpb.SourceInfo
}

Ast interface 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 ParsedExprToAst

func ParsedExprToAst(parsedExpr *exprpb.ParsedExpr) Ast

ParsedExprToAst converts a parsed expression proto message to an Ast.

type Env

type Env interface {
	// Extend the current environment with additional options to produce a new Env.
	Extend(opts ...EnvOption) (Env, error)

	// Check performs type-checking on the input Ast and yields a checked Ast and/or set of Issues.
	//
	// Checking 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.
	Check(ast Ast) (Ast, *Issues)

	// Parse parses the input expression value `txt` to a Ast and/or a set of Issues.
	//
	// This form of Parse creates a common.Source value for the input `txt` and forwards to the
	// ParseSource method.
	Parse(txt string) (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.
	ParseSource(src common.Source) (Ast, *Issues)

	// Program generates an evaluable instance of the Ast within the environment (Env).
	Program(ast Ast, opts ...ProgramOption) (Program, error)

	// TypeAdapter returns the `ref.TypeAdapter` configured for the environment.
	TypeAdapter() ref.TypeAdapter

	// TypeProvider returns the `ref.TypeProvider` configured for the environment.
	TypeProvider() ref.TypeProvider
}

Env defines functions for parsing and type-checking expressions against a set of user-defined constants, variables, and functions. The Env interface also defines a method for generating evaluable programs from parsed and checked Asts.

func NewEnv

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

NewEnv creates an Env instance suitable for parsing and checking expressions against a set of user-defined constants, variables, and functions. Macros and the standard built-ins are enabled by default.

See the EnvOptions for the options that can be used to configure the environment.

type EnvOption

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

EnvOption is a functional interface for configuring the environment.

func ClearBuiltIns

func ClearBuiltIns() EnvOption

ClearBuiltIns option removes all standard types, operators, and macros from the environment.

Note: This option must be specified before Declarations and/or Macros if used together.

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.

Note: This option is a no-op when used with ClearBuiltIns, and must be used before Macros if used together.

func Container

func Container(pkg 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 CustomTypeAdapter

func CustomTypeAdapter(adapter ref.TypeAdapter) EnvOption

CustomTypeAdapter swaps the default ref.TypeAdapter 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 ref.TypeProvider) EnvOption

CustomTypeProvider swaps the default ref.TypeProvider implementation with a custom one.

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: This option must be specified after ClearBuiltIns if both are used together.

func HomogeneousAggregateLiterals

func HomogeneousAggregateLiterals() EnvOption

HomogeneousAggregateLiterals option ensures that list and map literal entry types must agree during type-checking.

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 Macros

func Macros(macros ...parser.Macro) EnvOption

Macros option extends the macro set configured in the environment.

Note: This option must be specified after ClearBuiltIns and/or ClearMacros if used together.

func TypeDescs

func TypeDescs(descs ...interface{}) EnvOption

TypeDescs adds type declarations for one or more protocol buffer FileDescriptorProtos or FileDescriptorSets. Note that types added via descriptor will not be able to instantiate messages, and so are only useful for Check() operations.

func Types

func Types(addTypes ...interface{}) 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.

type EvalDetails

type EvalDetails interface {
	// State of the evaluation, non-nil if the OptTrackState or OptExhaustiveEval is specified
	// within EvalOptions.
	State() interpreter.EvalState
}

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

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. This flag is useful when the expression will be evaluated repeatedly against
	// a series of different inputs.
	OptOptimize EvalOption = 1 << iota
)

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

func NewIssues(errs *common.Errors) *Issues

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

func (*Issues) Append

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

Append collects the issues from another Issues struct into the current 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() []common.Error

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

func (*Issues) String

func (i *Issues) String() string

String converts the issues to a suitable display string.

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]interface{}`.
	//
	// If the `OptTrackState` 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(vars interface{}) (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 CustomAttributeFactory

func CustomAttributeFactory(attrs interpreter.AttributeFactory) ProgramOption

CustomAttributeFactory adjusts the variable and field resolution behavior of the Program.

An expression containing a field references and/or indexing expressions is considered an Attribute. An Attribute is a variable or object reference with zero or more Qualifier that values determine which piece of data is relevant to the computation. When an Attribute expression is encountered, the runtime resolves the Attribute to a concrete value.

An AttributeFactory may be generic or it may be deeply aware of the objects which can appear within CEL expressions. By default a generic AttributeFactory is created if a custom one is not set.

func EvalOptions

func EvalOptions(opts ...EvalOption) ProgramOption

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

func Functions

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

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

func Globals

func Globals(vars interface{}) 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.

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

type Source

type Source interface {
	common.Source
}

Source interface representing a user-provided expression.

Jump to

Keyboard shortcuts

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