kubernetes/vendor/github.com/google/cel-go/interpreter/interpreter.go

138 lines
4.7 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)
}
// 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.
func TrackState(state EvalState) InterpretableDecorator {
observer := func(id int64, val ref.Val) {
state.SetValue(id, val)
}
return decObserveEval(observer)
}
// 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(state EvalState) InterpretableDecorator {
ex := decDisableShortcircuits()
obs := TrackState(state)
return func(i Interpretable) (Interpretable, error) {
var err error
i, err = ex(i)
if err != nil {
return nil, err
}
return obs(i)
}
}
// 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()
}
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 gerenated 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)
}