diff --git a/cel/cel_test.go b/cel/cel_test.go index 018389b4..581e2855 100644 --- a/cel/cel_test.go +++ b/cel/cel_test.go @@ -564,6 +564,21 @@ func Benchmark_EvalOptions(b *testing.B) { } } +func Test_EnvExtension(t *testing.T) { + e, _ := NewEnv( + Container("google.api.expr.v1alpha1"), + Types(&exprpb.Expr{}), + Declarations( + decls.NewIdent("expr", + decls.NewObjectType("google.api.expr.v1alpha1.Expr"), nil), + ), + ) + e2, _ := e.Extend() + if e == e2 { + t.Error("Got object equality, wanted separate objects") + } +} + func Test_ParseAndCheckConcurrently(t *testing.T) { e, _ := NewEnv( Container("google.api.expr.v1alpha1"), diff --git a/cel/env.go b/cel/env.go index c04ad661..fd465a13 100644 --- a/cel/env.go +++ b/cel/env.go @@ -61,6 +61,9 @@ type Ast interface { // constants, variables, and functions. The Env interface also defines a method for generating // evaluable programs from parsed and checked Asts. 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. @@ -109,7 +112,7 @@ type Issues interface { // See the EnvOptions for the options that can be used to configure the environment. func NewEnv(opts ...EnvOption) (Env, error) { registry := types.NewRegistry() - e := &env{ + return (&env{ declarations: checker.StandardDeclarations(), macros: parser.AllMacros, pkg: packages.DefaultPackage, @@ -117,7 +120,18 @@ func NewEnv(opts ...EnvOption) (Env, error) { adapter: registry, enableBuiltins: true, enableDynamicAggregateLiterals: true, - } + }).configure(opts...) +} + +// Extend the current environment with additional options to produce a new Env. +func (e *env) Extend(opts ...EnvOption) (Env, error) { + ext := &env{} + *ext = *e + return ext.configure(opts...) +} + +// configure applies a series of EnvOptions to the current environment. +func (e *env) configure(opts ...EnvOption) (Env, error) { // Customized the environment using the provided EnvOption values. If an error is // generated at any step this, will be returned as a nil Env with a non-nil error. var err error