mirror of
				https://github.com/k3s-io/kubernetes.git
				synced 2025-11-03 23:40:03 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			218 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			218 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright 2018 Google LLC
 | 
						|
//
 | 
						|
// Licensed under the Apache License, Version 2.0 (the "License");
 | 
						|
// you may not use this file except in compliance with the License.
 | 
						|
// You may obtain a copy of the License at
 | 
						|
//
 | 
						|
//      http://www.apache.org/licenses/LICENSE-2.0
 | 
						|
//
 | 
						|
// Unless required by applicable law or agreed to in writing, software
 | 
						|
// distributed under the License is distributed on an "AS IS" BASIS,
 | 
						|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
						|
// See the License for the specific language governing permissions and
 | 
						|
// limitations under the License.
 | 
						|
 | 
						|
// Package interpreter provides functions to evaluate parsed expressions with
 | 
						|
// the option to augment the evaluation with inputs and functions supplied at
 | 
						|
// evaluation time.
 | 
						|
package interpreter
 | 
						|
 | 
						|
import (
 | 
						|
	"github.com/google/cel-go/common/containers"
 | 
						|
	"github.com/google/cel-go/common/types/ref"
 | 
						|
	"github.com/google/cel-go/interpreter/functions"
 | 
						|
 | 
						|
	exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
 | 
						|
)
 | 
						|
 | 
						|
// Interpreter generates a new Interpretable from a checked or unchecked expression.
 | 
						|
type Interpreter interface {
 | 
						|
	// NewInterpretable creates an Interpretable from a checked expression and an
 | 
						|
	// optional list of InterpretableDecorator values.
 | 
						|
	NewInterpretable(checked *exprpb.CheckedExpr,
 | 
						|
		decorators ...InterpretableDecorator) (Interpretable, error)
 | 
						|
 | 
						|
	// NewUncheckedInterpretable returns an Interpretable from a parsed expression
 | 
						|
	// and an optional list of InterpretableDecorator values.
 | 
						|
	NewUncheckedInterpretable(expr *exprpb.Expr,
 | 
						|
		decorators ...InterpretableDecorator) (Interpretable, error)
 | 
						|
}
 | 
						|
 | 
						|
// EvalObserver is a functional interface that accepts an expression id and an observed value.
 | 
						|
// The id identifies the expression that was evaluated, the programStep is the Interpretable or Qualifier that
 | 
						|
// was evaluated and value is the result of the evaluation.
 | 
						|
type EvalObserver func(id int64, programStep interface{}, value ref.Val)
 | 
						|
 | 
						|
// Observe constructs a decorator that calls all the provided observers in order after evaluating each Interpretable
 | 
						|
// or Qualifier during program evaluation.
 | 
						|
func Observe(observers ...EvalObserver) InterpretableDecorator {
 | 
						|
	if len(observers) == 1 {
 | 
						|
		return decObserveEval(observers[0])
 | 
						|
	}
 | 
						|
	observeFn := func(id int64, programStep interface{}, val ref.Val) {
 | 
						|
		for _, observer := range observers {
 | 
						|
			observer(id, programStep, val)
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return decObserveEval(observeFn)
 | 
						|
}
 | 
						|
 | 
						|
// EvalCancelledError represents a cancelled program evaluation operation.
 | 
						|
type EvalCancelledError struct {
 | 
						|
	Message string
 | 
						|
	// Type identifies the cause of the cancellation.
 | 
						|
	Cause CancellationCause
 | 
						|
}
 | 
						|
 | 
						|
func (e EvalCancelledError) Error() string {
 | 
						|
	return e.Message
 | 
						|
}
 | 
						|
 | 
						|
// CancellationCause enumerates the ways a program evaluation operation can be cancelled.
 | 
						|
type CancellationCause int
 | 
						|
 | 
						|
const (
 | 
						|
	// ContextCancelled indicates that the operation was cancelled in response to a Golang context cancellation.
 | 
						|
	ContextCancelled CancellationCause = iota
 | 
						|
 | 
						|
	// CostLimitExceeded indicates that the operation was cancelled in response to the actual cost limit being
 | 
						|
	// exceeded.
 | 
						|
	CostLimitExceeded
 | 
						|
)
 | 
						|
 | 
						|
// TODO: Replace all usages of TrackState with EvalStateObserver
 | 
						|
 | 
						|
// TrackState decorates each expression node with an observer which records the value
 | 
						|
// associated with the given expression id. EvalState must be provided to the decorator.
 | 
						|
// This decorator is not thread-safe, and the EvalState must be reset between Eval()
 | 
						|
// calls.
 | 
						|
// DEPRECATED: Please use EvalStateObserver instead. It composes gracefully with additional observers.
 | 
						|
func TrackState(state EvalState) InterpretableDecorator {
 | 
						|
	return Observe(EvalStateObserver(state))
 | 
						|
}
 | 
						|
 | 
						|
// EvalStateObserver provides an observer which records the value
 | 
						|
// associated with the given expression id. EvalState must be provided to the observer.
 | 
						|
// This decorator is not thread-safe, and the EvalState must be reset between Eval()
 | 
						|
// calls.
 | 
						|
func EvalStateObserver(state EvalState) EvalObserver {
 | 
						|
	return func(id int64, programStep interface{}, val ref.Val) {
 | 
						|
		state.SetValue(id, val)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// ExhaustiveEval replaces operations that short-circuit with versions that evaluate
 | 
						|
// expressions and couples this behavior with the TrackState() decorator to provide
 | 
						|
// insight into the evaluation state of the entire expression. EvalState must be
 | 
						|
// provided to the decorator. This decorator is not thread-safe, and the EvalState
 | 
						|
// must be reset between Eval() calls.
 | 
						|
func ExhaustiveEval() InterpretableDecorator {
 | 
						|
	ex := decDisableShortcircuits()
 | 
						|
	return func(i Interpretable) (Interpretable, error) {
 | 
						|
		return ex(i)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// InterruptableEval annotates comprehension loops with information that indicates they
 | 
						|
// should check the `#interrupted` state within a custom Activation.
 | 
						|
//
 | 
						|
// The custom activation is currently managed higher up in the stack within the 'cel' package
 | 
						|
// and should not require any custom support on behalf of callers.
 | 
						|
func InterruptableEval() InterpretableDecorator {
 | 
						|
	return decInterruptFolds()
 | 
						|
}
 | 
						|
 | 
						|
// Optimize will pre-compute operations such as list and map construction and optimize
 | 
						|
// call arguments to set membership tests. The set of optimizations will increase over time.
 | 
						|
func Optimize() InterpretableDecorator {
 | 
						|
	return decOptimize()
 | 
						|
}
 | 
						|
 | 
						|
// RegexOptimization provides a way to replace an InterpretableCall for a regex function when the
 | 
						|
// RegexIndex argument is a string constant. Typically, the Factory would compile the regex pattern at
 | 
						|
// RegexIndex and report any errors (at program creation time) and then use the compiled regex for
 | 
						|
// all regex function invocations.
 | 
						|
type RegexOptimization struct {
 | 
						|
	// Function is the name of the function to optimize.
 | 
						|
	Function string
 | 
						|
	// OverloadID is the ID of the overload to optimize.
 | 
						|
	OverloadID string
 | 
						|
	// RegexIndex is the index position of the regex pattern argument. Only calls to the function where this argument is
 | 
						|
	// a string constant will be delegated to this optimizer.
 | 
						|
	RegexIndex int
 | 
						|
	// Factory constructs a replacement InterpretableCall node that optimizes the regex function call. Factory is
 | 
						|
	// provided with the unoptimized regex call and the string constant at the RegexIndex argument.
 | 
						|
	// The Factory may compile the regex for use across all invocations of the call, return any errors and
 | 
						|
	// return an interpreter.NewCall with the desired regex optimized function impl.
 | 
						|
	Factory func(call InterpretableCall, regexPattern string) (InterpretableCall, error)
 | 
						|
}
 | 
						|
 | 
						|
// CompileRegexConstants compiles regex pattern string constants at program creation time and reports any regex pattern
 | 
						|
// compile errors.
 | 
						|
func CompileRegexConstants(regexOptimizations ...*RegexOptimization) InterpretableDecorator {
 | 
						|
	return decRegexOptimizer(regexOptimizations...)
 | 
						|
}
 | 
						|
 | 
						|
type exprInterpreter struct {
 | 
						|
	dispatcher  Dispatcher
 | 
						|
	container   *containers.Container
 | 
						|
	provider    ref.TypeProvider
 | 
						|
	adapter     ref.TypeAdapter
 | 
						|
	attrFactory AttributeFactory
 | 
						|
}
 | 
						|
 | 
						|
// NewInterpreter builds an Interpreter from a Dispatcher and TypeProvider which will be used
 | 
						|
// throughout the Eval of all Interpretable instances generated from it.
 | 
						|
func NewInterpreter(dispatcher Dispatcher,
 | 
						|
	container *containers.Container,
 | 
						|
	provider ref.TypeProvider,
 | 
						|
	adapter ref.TypeAdapter,
 | 
						|
	attrFactory AttributeFactory) Interpreter {
 | 
						|
	return &exprInterpreter{
 | 
						|
		dispatcher:  dispatcher,
 | 
						|
		container:   container,
 | 
						|
		provider:    provider,
 | 
						|
		adapter:     adapter,
 | 
						|
		attrFactory: attrFactory}
 | 
						|
}
 | 
						|
 | 
						|
// NewStandardInterpreter builds a Dispatcher and TypeProvider with support for all of the CEL
 | 
						|
// builtins defined in the language definition.
 | 
						|
func NewStandardInterpreter(container *containers.Container,
 | 
						|
	provider ref.TypeProvider,
 | 
						|
	adapter ref.TypeAdapter,
 | 
						|
	resolver AttributeFactory) Interpreter {
 | 
						|
	dispatcher := NewDispatcher()
 | 
						|
	dispatcher.Add(functions.StandardOverloads()...)
 | 
						|
	return NewInterpreter(dispatcher, container, provider, adapter, resolver)
 | 
						|
}
 | 
						|
 | 
						|
// NewIntepretable implements the Interpreter interface method.
 | 
						|
func (i *exprInterpreter) NewInterpretable(
 | 
						|
	checked *exprpb.CheckedExpr,
 | 
						|
	decorators ...InterpretableDecorator) (Interpretable, error) {
 | 
						|
	p := newPlanner(
 | 
						|
		i.dispatcher,
 | 
						|
		i.provider,
 | 
						|
		i.adapter,
 | 
						|
		i.attrFactory,
 | 
						|
		i.container,
 | 
						|
		checked,
 | 
						|
		decorators...)
 | 
						|
	return p.Plan(checked.GetExpr())
 | 
						|
}
 | 
						|
 | 
						|
// NewUncheckedIntepretable implements the Interpreter interface method.
 | 
						|
func (i *exprInterpreter) NewUncheckedInterpretable(
 | 
						|
	expr *exprpb.Expr,
 | 
						|
	decorators ...InterpretableDecorator) (Interpretable, error) {
 | 
						|
	p := newUncheckedPlanner(
 | 
						|
		i.dispatcher,
 | 
						|
		i.provider,
 | 
						|
		i.adapter,
 | 
						|
		i.attrFactory,
 | 
						|
		i.container,
 | 
						|
		decorators...)
 | 
						|
	return p.Plan(expr)
 | 
						|
}
 |