Fast, portable, non-Turing complete expression evaluation with gradual typing (Go)

Overview

Common Expression Language

Go Report Card GoDoc

The Common Expression Language (CEL) is a non-Turing complete language designed for simplicity, speed, safety, and portability. CEL's C-like syntax looks nearly identical to equivalent expressions in C++, Go, Java, and TypeScript.

// Check whether a resource name starts with a group name.
resource.name.startsWith("/groups/" + auth.claims.group)
// Determine whether the request is in the permitted time window.
request.time - resource.age < duration("24h")
// Check whether all resource names in a list match a given filter.
auth.claims.email_verified && resources.all(r, r.startsWith(auth.claims.email))

A CEL "program" is a single expression. The examples have been tagged as java, go, and typescript within the markdown to showcase the commonality of the syntax.

CEL is ideal for lightweight expression evaluation when a fully sandboxed scripting language is too resource intensive. To get started, try the Codelab.

A dashboard that shows results of cel-go conformance tests can be found here.



Overview

Determine the variables and functions you want to provide to CEL. Parse and check an expression to make sure it's valid. Then evaluate the output AST against some input. Checking is optional, but strongly encouraged.

Environment Setup

Let's expose name and group variables to CEL using the cel.Declarations environment option:

import(
    "github.com/google/cel-go/cel"
    "github.com/google/cel-go/checker/decls"
)

env, err := cel.NewEnv(
    cel.Declarations(
        decls.NewVar("name", decls.String),
        decls.NewVar("group", decls.String)))

That's it. The environment is ready to be use for parsing and type-checking. CEL supports all the usual primitive types in addition to lists, maps, as well as first-class support for JSON and Protocol Buffers.

Parse and Check

The parsing phase indicates whether the expression is syntactically valid and expands any macros present within the environment. Parsing and checking are more computationally expensive than evaluation, and it is recommended that expressions be parsed and checked ahead of time.

The parse and check phases are combined for convenience into the Compile step:

ast, issues := env.Compile(`name.startsWith("/groups/" + group)`)
if issues != nil && issues.Err() != nil {
    log.Fatalf("type-check error: %s", issues.Err())
}
prg, err := env.Program(ast)
if err != nil {
    log.Fatalf("program construction error: %s", err)
}

The cel.Program generated at the end of parse and check is stateless, thread-safe, and cachable.

Type-checking in an optional, but strongly encouraged, step that can reject some semantically invalid expressions using static analysis. Additionally, the check produces metadata which can improve function invocation performance and object field selection at evaluation-time.

Macros

Macros are optional but enabled by default. Macros were introduced to support optional CEL features that might not be desired in all use cases without the syntactic burden and complexity such features might desire if they were part of the core CEL syntax. Macros are expanded at parse time and their expansions are type-checked at check time.

For example, when macros are enabled it is possible to support bounded iteration / fold operators. The macros all, exists, exists_one, filter, and map are particularly useful for evaluating a single predicate against list and map values.

// Ensure all tweets are less than 140 chars
tweets.all(t, t.size() <= 140)

The has macro is useful for unifying field presence testing logic across protobuf types and dynamic (JSON-like) types.

// Test whether the field is a non-default value if proto-based, or defined
// in the JSON case.
has(message.field)

Both cases traditionally require special syntax at the language level, but these features are exposed via macros in CEL.

Evaluate

Now, evaluate for fun and profit. The evaluation is thread-safe and side-effect free. Many different inputs can be send to the same cel.Program and if fields are present in the input, but not referenced in the expression, they are ignored.

// The `out` var contains the output of a successful evaluation.
// The `details' var would contain intermediate evaluation state if enabled as
// a cel.ProgramOption. This can be useful for visualizing how the `out` value
// was arrive at.
out, details, err := prg.Eval(map[string]interface{}{
    "name": "/groups/acme.co/documents/secret-stuff",
    "group": "acme.co"})
fmt.Println(out) // 'true'

Partial State

What if name hadn't been supplied? CEL is designed for this case. In distributed apps it is not uncommon to have edge caches and central services. If possible, evaluation should happen at the edge, but it isn't always possible to know the full state required for all values and functions present in the CEL expression.

To improve the odds of successful evaluation with partial state, CEL uses commutative logical operators &&, ||. If an error or unknown value (not the same thing) is encountered on the left-hand side, the right hand side is evaluated also to determine the outcome. While it is possible to implement evaluation with partial state without this feature, this method was chosen because it aligns with the semantics of SQL evaluation and because it's more robust to evaluation against dynamic data types such as JSON inputs.

In the following truth-table, the symbols <x> and <y> represent error or unknown values, with the ? indicating that the branch is not taken due to short-circuiting. When the result is <x, y> this means that the both args are possibly relevant to the result.

Expression Result
false && ? false
true && false false
<x> && false false
true && true true
true && <x> <x>
<x> && true <x>
<x> && <y> <x, y>
true || ? true
false || true true
<x> || true true
false || false false
false || <x> <x>
<x> || false <x>
<x> || <y> <x, y>

In the cases where unknowns are expected, cel.EvalOptions(cel.OptTrackState) should be enabled. The details value returned by Eval() will contain the intermediate evaluation values and can be provided to the interpreter.Prune function to generate a residual expression. e.g.:

// Residual when `name` omitted:
name.startsWith("/groups/acme.co")

This technique can be useful when there are variables that are expensive to compute unless they are absolutely needed. This functionality will be the focus of many future improvements, so keep an eye out for more goodness here!

Errors

Parse and check errors have friendly error messages with pointers to where the issues occur in source:

ERROR: <input>:1:40: undefined field 'undefined'
    | TestAllTypes{single_int32: 1, undefined: 2}
    | .......................................^`,

Both the parsed and checked expressions contain source position information about each node that appears in the output AST. This information can be used to determine error locations at evaluation time as well.

Install

CEL-Go supports modules and uses semantic versioning. For more info see the Go Modules docs.

And of course, there is always the option to build from source directly.

Common Questions

Why not JavaScript, Lua, or WASM?

JavaScript and Lua are rich languages that require sandboxing to execute safely. Sandboxing is costly and factors into the "what will I let users evaluate?" question heavily when the answer is anything more than O(n) complexity.

CEL evaluates linearly with respect to the size of the expression and the input being evaluated when macros are disabled. The only functions beyond the built-ins that may be invoked are provided by the host environment. While extension functions may be more complex, this is a choice by the application embedding CEL.

But, why not WASM? WASM is an excellent choice for certain applications and is far superior to embedded JavaScript and Lua, but it does not have support for garbage collection and non-primitive object types require semi-expensive calls across modules. In most cases CEL will be faster and just as portable for its intended use case, though for node.js and web-based execution CEL too may offer a WASM evaluator with direct to WASM compilation.

Do I need to Parse and Check?

Checking is an optional, but strongly suggested, step in CEL expression validation. It is sufficient in some cases to simply Parse and rely on the runtime bindings and error handling to do the right thing.

Where can I learn more about the language?

  • See the CEL Spec for the specification and conformance test suite.
  • Ask for support on the CEL Go Discuss Google group.

Where can I learn more about the internals?

  • See GoDoc to learn how to integrate CEL into services written in Go.
  • See the CEL C++ toolchain (under development) for information about how to integrate CEL evaluation into other environments.

How can I contribute?

Some tests don't work with go test?

A handful of tests rely on Bazel. In particular dynamic proto support at check time and the conformance test driver require Bazel to coordinate the test inputs:

bazel test ...

License

Released under the Apache License.

Disclaimer: This is not an official Google product.

Comments
  • Resolve multiple packages with cel.Container

    Resolve multiple packages with cel.Container

    Feature request checklist

    • [X] There are no issues that match the desired change
    • [ ] The change is large enough it can't be addressed with a simple Pull Request
    • [ ] If this is a bug, please file a Bug Report.

    Change

    Currently, cel.Container can be used to specify a namespace for symbol resolution. For example:

    env, _ := cel.NewEnv(
    	cel.Container("a"),
    	cel.Types(&apb.A{}),
    )
    ast, _ := env.Compile("A{}")
    prg, _ := env.Program(ast)
    prg.Eval(map[string]interface{}{})
    

    In order to write programs that reference multiple protobuf packages, we are forced to use fully qualified names for types outside the container:

    env, _ := cel.NewEnv(
    	cel.Container("a"),
    	cel.Types(&apb.A{}, &bpb.B{}),
    )
    ast, _ := env.Compile("b.B{}")
    prg, _ := env.Program(ast)
    prg.Eval(map[string]interface{}{})
    

    Example

    We should provide the ability to resolve multiple namespaces. There are two options:

    1. Container could take multiple package names:
    func Container(pkgs ...string) EnvOption
    
    1. Env could be initialized with a custom packages.Packager:
    func Package(pkg packages.Packager) EnvOption
    

    Alternatives considered

    It’s possible that both these methods would be useful. Here is a sample implementation:

    package cel
    
    func Container(pkgs ...string) EnvOption {
    	return func(e *Env) (*Env, error) {
    		return e.Package(packages.NewPackage(pkgs...))
    	}
    }
    
    func Package(pkg packages.Packager) EnvOption {
    	return func(e *Env) (*Env, error) {
    		e.pkg = pkg
    		return e, nil
    	}
    }
    
    //////
    
    package packages
    
    type defaultPackage struct {
    	pkgs []string
    }
    
    func NewPackage(pkgs ...string) packages.Packager {
    	seen := make(map[string]bool, len(pkgs))
    
    	var p defaultPackage
    	for _, pkg := range pkgs {
    		if seen[pkg] {
    			continue
    		}
    		p.pkgs = append(p.pkgs, p.pkgs)
    		seen[pkg] = true
    	}
    	return &p
    }
    
    func (p *defaultPackage) Package() string {
    	return strings.Join(p.pkgs, " ")
    }
    
    func (p *defaultPackage) ResolveCandidateNames(name string) []string {
    	if strings.HasPrefix(name, ".") {
    		return []string{name[1:]}
    	}
    
    	if len(p.pkg) == 0 {
    		return []string{name}
    	}
    
    	for _, nextPkg := range p.pkgs {
    		candidates := []string{nextPkg + "." + name}
    		for i := strings.LastIndex(nextPkg, "."); i >= 0; i = strings.LastIndex(nextPkg, ".") {
    			nextPkg = nextPkg[:i]
    			candidates = append(candidates, nextPkg+"."+name)
    		}
    	}
    
    	return append(candidates, name)
    }
    
    enhancement 
    opened by sfllaw 23
  • Create an extension library for working with strings

    Create an extension library for working with strings

    This code is based on FR #306 which requested support for built-in substrings. While substrings are not part of the core CEL spec, such functions are a common ask and the following is an implementation of such functions as extensions which can be layered onto the core CEL spec.

    Closes #306

    opened by TristonianJones 14
  • Fix nested CallExpr cost estimation

    Fix nested CallExpr cost estimation

    This PR fixes instances where cost estimation is used on expressions where a CallExpr is nested inside of another CallExpr and math.MaxUint64 is incorrectly returned. The test case included with this PR shows an example of where this can happen; == is treated as a function call/CallExpr, and will call sizeEstimate on its left and right-hand expressions. sizeEstimate will then try to call AstNode.ComputedSize before trying EstimateSize and finally returning math.MaxUint64 for an upper limit.

    That constant will get returned for operator-based CallExprs inside CallExprs whenever the inner one lacks an EstimateSize, such as with list.size(). Instead, this PR checks for CallExpr inside SizeEstimate and returns a min/max cost of 1.

    The original issue was first reported in https://github.com/kubernetes/kubernetes/issues/111769.

    opened by DangerOnTheRanger 12
  • Allow building Ast with textual contents

    Allow building Ast with textual contents

    Unless I am missing something, it is currently not possible to build an Ast from an exprpb.ParsedExpr or exprpb.CheckedExpr with source contents. As a consequence, if an Ast built from ParsedExprToAst or CheckedExprToAst is checked or executed, the error messages will not show code snippets.

    Introduce a CheckedExprToAstWithSource and ParsedExprToAstWithSource to allow providing the source contents.

    opened by damz 12
  • Optimize type conversion functions.

    Optimize type conversion functions.

    Unary type-conversion functions with literal arguments should be evaluated eagerly when the cel.EvalOptions(cel.OptOptimize) flag is set. The conversion will also ensure that if an error is encountered when evaluating these functions, such as when constructing timestamps or durations from strings, the evaluation will result in an error in the env.Program call.

    This is not a perfect fix for #359, but it can be used to assist with correctness checks.

    opened by TristonianJones 10
  • Comparing timestamps?

    Comparing timestamps?

    Hi, sorry for the lame question -- how can I compare timestamps using CEL + this library?

    I tried timestamp(0) == timestamp(0) but I get false every time.

    Is there a reference I could read about how to do this?

    opened by mholt 10
  • Reject dyn inputs to strongly typed functions at check time.

    Reject dyn inputs to strongly typed functions at check time.

    We're evaluating this for our filter expressions and we found a weird behaviour which I don't know if its related to our environment or the lib itself. The issue comes when using the in operator and defining a list with different types. As far as i know, the parsed expression checking enforces this by default, or this is what i understood by reading this paragraph on the langdef spec:

    The type checker also introduces the dyn type, which is the union of all other types. Therefore the type checker could accept a list of heterogeneous values as dyn([1, 3.14, "foo"]), which is tiven the type list(dyn). The standard function dyn has no effect at runtime, but signals to the type checker that its argument should be considered of type dyn, list(dyn), or a dyn-valued map.

    Take this as an example:

    • Declare Parser
    // Parser is our expr parser
    type Parser struct {
    	env *checker.Env
    }
    
    // NewParser instantiates the Parser object
    func NewParser(message proto.Message, allowedFields []string) (*Parser, error) {
    	// attach protobuf & initialize env
    	pkg := proto.MessageName(message)
    	typeProvider := types.NewProvider(message)
    	exprType := decls.NewObjectType(pkg)
    
    	// create standard env
    	env := checker.NewEnv(packages.NewPackage(pkg), typeProvider)
    	if err := env.Add(standardDeclarations()...); err != nil {
    		return nil, err
    	}
    
    	// add types tailored to our specific use-case.
    	for _, filterable := range allowedFields {
    		fieldType, ok := typeProvider.FindFieldType(exprType, filterable)
    		if !ok {
    			return nil, fmt.Errorf("expr: couldn't find field %s", filterable)
    		}
    		err := env.Add(decls.NewIdent(filterable, fieldType.Type, nil))
    		if err != nil {
    			return nil, err
    		}
    	}
    
    	return &Parser{env: env}, nil
    }
    
    func standardDeclarations() []*exprpb.Decl {
    	return []*exprpb.Decl{
    		decls.NewFunction(operators.LogicalAnd,
    			decls.NewOverload(overloads.LogicalAnd,
    				[]*exprpb.Type{decls.Bool, decls.Bool}, decls.Bool)),
    		decls.NewFunction(operators.LogicalOr,
    			decls.NewOverload(overloads.LogicalOr,
    				[]*exprpb.Type{decls.Bool, decls.Bool}, decls.Bool)),
    		decls.NewFunction(operators.Equals,
    			decls.NewOverload(overloads.Equals,
    				[]*exprpb.Type{decls.String, decls.String}, decls.Bool)),
    		decls.NewFunction(operators.In,
    			decls.NewOverload(overloads.InList,
    				[]*exprpb.Type{decls.String, decls.NewListType(decls.String)}, decls.Bool)),
    	}
    }
    
    • Parse filter
    // Parse produces a database friendly expr from a cel string expr
    func (e *Parser) Parse(filter string) (*Expr, error) {
    	if filter == "" {
    		return nil, nil
    	}
    	// parse expr
    	src := common.NewTextSource(filter)
    	expr, errs := parser.Parse(src)
    	if len(errs.GetErrors()) != 0 {
    		return nil, errors.New(errs.ToDisplayString())
    	}
    
    	// check expr against env
    	checkedExpr, errs := checker.Check(expr, src, e.env)
    	if len(errs.GetErrors()) != 0 {
    		return nil, errors.New(errs.ToDisplayString())
    	}
    
    	return &Expr{expr: checkedExpr.Expr}, nil
    }
    

    I would expect the checker to fail but it returns the checked expression without complaining.

    Can anyone point to the right direction if i'm missing something?

    Thanks for this great library by the way.

    bug P3 
    opened by glerchundi 10
  • Runtime cost calculation

    Runtime cost calculation

    Introduce runtime cost calculation into CEL.

    The work is part of this issue

    The current PR includes:

    • Add runtime cost calculation into evaluation path
    • Test to verify runtime cost calculation
    • Test to verify runtime cost fell into estimation cost range
    • Test to allow cost calculation for extension function

    Todo in following PR:

    • Add cancellation
    • Add more test for large input
    • Add test coverage for aligning runtime cost with estimate cost
    opened by cici37 8
  • Update README.md

    Update README.md

    Hi,

    Awesome project 😀 But I found this in README.md:

    ... https://github.com/antonmedv/expr ... StartsWith(name, Concat("/groups/", group)) // Expr BenchmarkExpr-8 1000000 1402 ns/op

    Please, update README.md with new results:

    ❯❯❯ go test -bench=startswith
    goos: darwin
    goarch: amd64
    pkg: github.com/antonmedv/golang-expression-evaluation-comparison
    Benchmark_celgo_startswith-8   	 3000000	       466 ns/op
    Benchmark_expr_startswith-8    	 5000000	       362 ns/op
    PASS
    ok  	github.com/antonmedv/golang-expression-evaluation-comparison	4.081s
    
    opened by antonmedv 8
  • go get or go build does not work for repo

    go get or go build does not work for repo

    Describe the bug As mentioned in https://github.com/google/cel-go#install

    go mod init <my-cel-app>
    go build ./...
    

    or

    go get -u github.com/google/cel-go/...
    

    Does not work and results in the following error:

    go build -o myproj.bin -v
    go: finding github.com/google/cel-go/interpreter/functions latest
    go: finding github.com/google/cel-go/common/types latest
    go: finding github.com/google/cel-go/cel latest
    go: finding github.com/google/cel-go/common/types/ref latest
    go: finding github.com/google/cel-go/checker/decls latest
    go: finding github.com/google/cel-go/interpreter latest
    go: finding github.com/google/cel-go/common latest
    Fetching https://github.com?go-get=1
    go: finding github.com/google/cel-go/checker latest
    Parsing meta tags from https://github.com?go-get=1 (status code 200)
    build company.tech/rhnvrm/myproj cannot load github.com/google/cel-go/cel: cannot find module providing package github.com/google/cel-go/cel
    
    go get -u github.com/google/cel-go/...
    ...
    go: github.com/golang/[email protected]: parsing go.mod: unexpected module path "golang.org/x/lint"
    

    To fix this for now, I have done a git clone and added a replace directive

    This is my go.mod

    module company.tech/rhnvrm/myproj
    
    go 1.12
    
    require (
    	github.com/golang/protobuf v1.3.0
    	github.com/google/cel-go v0.2.0
    	google.golang.org/genproto v0.0.0-20190227213309-4f5b463f9597
    )
    
    replace github.com/google/cel-go v0.2.0 => ./celgo
    
    opened by rhnvrm 8
  • Speculative optimization: Use custom string serializer for Type

    Speculative optimization: Use custom string serializer for Type

    It seems that the generic text proto CompactStringMarshal is more expensive that hand-made one. Looking for feedback. I think we probably want to use a Struct as a hashmap key, but that would require building a new family of structs mirroring Types, since using proto Type does not seem to work.

    opened by kyessenov 8
  • Extension to support Golang structs as CEL types

    Extension to support Golang structs as CEL types

    Initial support for Golang struct types within CEL.

    Given a struct defined as follows, you could use the type definition within CEL as follows:

    package auth;
    
    type Account struct {
      Name string
      ID int64
    }
    
    env, err := cel.NewEnv(
        ext.NativeTypes(reflect.TypeOf(&auth.Account{})),
    )
    // ... check for errors ... 
    ast, iss := env.Compile(`auth.Account{Name: 'test', ID: 1234}`)
    // ... check for errors ... 
    prg, err := env.Program(ast)
    // ... check for errors ... 
    out, _, err := prg.Eval(cel.NoVars())
    reflect.DeepEqual(out.Value(), &auth.Account{Name: 'test', ID: 1234}) == true
    

    The ext.NativeTypes() option supports safe traversal over struct types, as well as support for has() and the new CEL optional value feature introduced with cel.OptionalTypes().

    As a future refinement a new cel tag may be introduced in order to make it possible to preserve the snake_case field names convention between Golang and protobuf if working with both type systems.

    Closes #408

    opened by TristonianJones 2
  • How to validate the array of self-defination struct?

    How to validate the array of self-defination struct?

    I have a self-defination struct like this

    type student {
        name string
        age int
    }
    

    then, I generate a array of "student"

    students := make([]*student, 0)
    students = append(students, &student{"123",18}),
    students = append(students, &student{"456",19}),
    students = append(students, &student{"789",20}),
    

    if the age of all the students is more than 17,it returns true,otherwise,returns false What should I do?

    question 
    opened by spencersong123 1
  • Normalize error messages from ANTLR

    Normalize error messages from ANTLR

    Feature request checklist

    • [X] There are no issues that match the desired change
    • [X] The change is large enough it can't be addressed with a simple Pull Request
    • [ ] If this is a bug, please file a Bug Report.

    Change Currently, when parse errors are detected, the ANTLR error message is passed through from CEL to the caller with some additional formatting to highlight where the error occurs. A recent update to the CEL grammar resulted in a shift in the error information from ANTLR which has the potential to break upstream tests relying on the exact contents of the original error from ANTLR.

    Example Introduce a flag-guarded change to normalize error messages from ANTLR in order to ensure that errors can be kept consistent even in the face of grammar updates.

    Alternatives considered Strip all ANTLR error messages and replace them with a general "invalid syntax" message since the error from ANTLR itself is not always easy to comprehend.

    opened by TristonianJones 0
  • Replace `exprpb.Type` references with `cel.Type`

    Replace `exprpb.Type` references with `cel.Type`

    Feature request checklist

    • [X] There are no issues that match the desired change
    • [X] The change is large enough it can't be addressed with a simple Pull Request
    • [ ] If this is a bug, please file a Bug Report.

    Change The top-level API currently emphasizes using cel.Type values rather than exprpb.Type values in an effort to reduce the protobuf surface area visible on the cel-go APIs. However, the ref.TypeProvider currently exposes a method to FindType and FindFieldType which return an exprpb.Type. This interface is used by a handful of customers to extend the CEL type-system, and creates a disconnect between the top-level API and the extensions.

    The change should introduce a new TypeProvider which can wrap the old style and produce cel.Type values from these methods for use within the type-checker and runtimes.

    Alternatives considered Provide new methods on the existing TypeProvider interface.

    • Functional, but would be a breaking API change for existing users.
    • Introduces a more complex migration burden of having to support both the old and new-style methods.
    opened by TristonianJones 0
  • Support context propagation on overloads

    Support context propagation on overloads

    These changes introduce :

    • a new interface functions.Overloader for keeping compatiblity with already defined functions.Overload structures
    • a new structure functions.ContextOverload for defining context capable overloads
    • the extension of the interpreter.Activation interface with context.Context
    • a small test for checking that context cancellation can be catched with underlying overloads

    The idea was to keep API compatibility while propagating the execution context to overload functions.

    Resolves #557

    opened by Neakxs 0
  • Support context propagation on overloads

    Support context propagation on overloads

    Feature request checklist

    • [x] There are no issues that match the desired change
    • [ ] The change is large enough it can't be addressed with a simple Pull Request
    • [ ] If this is a bug, please file a Bug Report.

    Change

    Currently, it is possible to use go contexts with the ContextEval(context.Context, interface{}) method. However, this context is not usable by function overloads.

    Example

    fn := &functions.ContextOverload{
        Operator: "longRunningOperation",
        Unary: func(ctx context.Context, value ref.Val) {
            if err := longRunningOperation(ctx, value.Value()); err != nil {
                return types.Bool(false)
            }
            return types.Bool(true)
        }
    }
    
    opened by Neakxs 2
Releases(v0.12.5)
  • v0.12.5(Aug 18, 2022)

    Fixes

    • Codelab module and codelab refactors [#567]
    • Use proto safe traversal accessors [#570]
    • Avoid exception for immutable list from folded expression [#574]
    • Fix nested CallExpr cost estimation [#571] (backported to v0.10.2, v0.11.5)

    New Contributors

    • @livebranch
    • @DangerOnTheRanger

    Full Changelog: https://github.com/google/cel-go/compare/v0.12.4...v0.12.5

    Source code(tar.gz)
    Source code(zip)
  • v0.12.4(Jul 14, 2022)

    Fixes

    • Ensure overloads are searched in the order they are declared [#566]
    • Augment dynamic dispatch to consider list and map element type information during overload resolution.

    Full Changelog: https://github.com/google/cel-go/compare/v0.12.3...v0.12.4

    Source code(tar.gz)
    Source code(zip)
  • v0.12.3(Jul 13, 2022)

    Fixes

    • Add the duration declarations in the new style when UTC is enabled [#565]

    Full Changelog: https://github.com/google/cel-go/compare/v0.12.2...v0.12.3

    Source code(tar.gz)
    Source code(zip)
  • v0.12.2(Jul 12, 2022)

    Features

    • Support formatting options when unparsing ASTs to strings [#559]

    Fixes

    • Add an applied features map for one-time only features [#564]

    New Contributors

    • @l46kok made their first contribution in https://github.com/google/cel-go/pull/559

    Full Changelog: https://github.com/google/cel-go/compare/v0.12.1...v0.12.2

    Source code(tar.gz)
    Source code(zip)
  • v0.12.1(Jul 11, 2022)

    Fixes

    • Fix the signature overlap check for parameterized types by [#563]

    Full Changelog: https://github.com/google/cel-go/compare/v0.12.0...v0.12.1

    Source code(tar.gz)
    Source code(zip)
  • v0.12.0(Jul 6, 2022)

    Features

    • Introduce a REPL for testing basic CEL expressions. [#539]
    • Add basic readme for REPL [#545]
    • Add REPL support for loading protobuf descriptors [#555]
    • Dispatcher refactor to improve function declaration, definition, and extension [#556]
    • Export the built-in parser macros individually [#429]

    Fixes

    Note, the cel-spec indicates that time operations should be UTC by default. To opt-in to this behavior see #560 for more details. In v0.13.+ this feature is expected to be enabled by default.

    • Provide an option to ensure time operations are in UTC by default [#560]
    • Ensure the recursion depth is being checked during parser AST visit [#542]
    • Add missing type specializations into the type-checker. [#543]
    • Support for proto2 group fields [#547]
    • Ensure that type substitutions consistently perform the 'occurs' check.[#550]
    • Ensure that the CheckedType is populated for group fields [#552]

    New Contributors

    • @jnthntatum made their first contribution in https://github.com/google/cel-go/pull/539

    Full Changelog: https://github.com/google/cel-go/compare/v0.11.4...v0.12.0

    Source code(tar.gz)
    Source code(zip)
  • v0.11.4(May 13, 2022)

    Fixes

    • Omit large error strings [#537]
    • Fix the occurs check to prevent tagging types as substitutions for themselves [#540]

    Full Changelog: https://github.com/google/cel-go/compare/v0.11.3...v0.11.4

    Source code(tar.gz)
    Source code(zip)
  • v0.11.3(May 5, 2022)

    Features

    • Allow functions to accept error and unknown args [#525]

    Fixes

    • Minor adjustment to type-tests to support custom Bool types by [#521]
    • Minor simplification of ValOrErr [#522]
    • Fix protobuf merge when types have different descriptor instances [#526]
    • Prevent clobbering vars maps provided by previous libs [#528]
    • Use gazelle-compatible repository name for antlr [#529]
    • Upgrade to ANTLR v4.10.1 and remove binary ANTLR tools [#533]
    • Set the error reporting limit to 100 for parity with C++ [#534]

    New Contributors

    • @lorenz made their first contribution in https://github.com/google/cel-go/pull/529

    Full Changelog: https://github.com/google/cel-go/compare/v0.11.2...v0.11.3

    Source code(tar.gz)
    Source code(zip)
  • v0.11.2(Mar 25, 2022)

    Fixes

    • Make the standard environment initialization lazy [#520]

    Full Changelog: https://github.com/google/cel-go/compare/v0.11.1...v0.11.2

    Source code(tar.gz)
    Source code(zip)
  • v0.11.1(Mar 24, 2022)

    Performance optimization release, ~5% performance gains in evaluation, and >95% performance gains in cel.NewEnv() setup.

    Fixes

    • Micro optimizations to type-testing utility functions [#518]
    • Improve mutable list documentation by [#516]
    • Copy validated declarations between checker.Env instances on extension [#347]

    Full Changelog: https://github.com/google/cel-go/compare/v0.11.0...v0.11.1

    Source code(tar.gz)
    Source code(zip)
  • v0.11.0(Mar 22, 2022)

    The v0.11.0 release introduces a sub-module for the server package used for conformance testing the cel-go package. The sub-module has been split out to remove the gRPC dependency related to the core CEL package and to reduce the overall size of the library import for users. Additionally, the CEL core dependencies have been vendored into the repo.

    In addition this release features a handful of fixes and improvements for heterogenous equality, code health, and runtime cost calculations.

    Features

    • Vendored dependencies and conformance sub-module [#508]

    Fixes

    • Fixes for map and list indexing across numeric types [#510]
    • Fix formatting and spelling lint [#511]
    • Use a zero-size type for variable-free activations [#513]
    • Simplify definition of cel.Source [#512]
    • Put cel package examples in package cel_test [#515]
    • Fix runtime cost ref.Val stack [#517]

    New Contributors

    • @kortschak made their first contribution in https://github.com/google/cel-go/pull/511

    Full Changelog: https://github.com/google/cel-go/compare/v0.10.1...v0.11.0

    Source code(tar.gz)
    Source code(zip)
  • v0.11.0-pre(Mar 14, 2022)

  • v0.10.1(Mar 10, 2022)

    Fixes

    • Add function name and result to CallCost and EstimatedCallCost [#506]
    • Add nil check and fix costTracker in contextEval [#507]

    Full Changelog: https://github.com/google/cel-go/compare/v0.10.0...v0.10.1

    Source code(tar.gz)
    Source code(zip)
  • v0.10.0(Mar 8, 2022)

    Features

    Heterogeneous Runtime Equality

    CEL currently only supports homogeneous equality via type-checking; however, where type inferences are limited, such as when working with JSON, the definition of runtime equality has been relaxed such that comparisons across type are permitted.

    • Protobuf equality uses the C++ MessageDifferencer::Equals behavior
    • Numeric equality treats all numeric types as though they occur on a single continuous number line
    • All other comparisons across type return false.

    This change will shift a certain category of runtime errors into non-errors.

    • Support heterogeneous null comparisons [#471]
    • Implement heterogeneous null comparisons for list and map [#472]
    • Numeric in/equality and comparisons across numeric types [#473]
    • Updates to cel-go proto equality to mirror C++ MessageDifferencer [#481]
    • Heterogeneous equality [#482]
    • Cross-type numeric declarations with opt-in [#484]

    Expression Cost Tracking

    Static analysis tools for better evaluation cost estimation with options to track and enforce these limits during runtime evaluation. This work deprecates and will replace the interpreter.Coster interface for heuristic costing of expressions.

    • EstimateCost API [#483]
    • Estimate costs for list and string concatenation and conditionals [#487]
    • Runtime cost calculation with limits [#494]
    • Adjust cost estimates to account for logical op short circuiting [#501]

    Additional Changes

    • Expose an option to track macro call replacements [#470]
    • Move ref.Val -> api.expr.Value converter to io.go [#480]
    • List append optimizations for comprehension loops (40x speed-up in filter, map) [#491]
    • Add join to strings ext library [#495]
    • Add option to compile regex constants at program creation time [#497]
    • Context Eval for interruptable evaluation [#502]

    Fixes

    • Ensure macro calls are tracked efficiently in lists and call targets by [#467]
    • Update the operator map structure [#466]
    • Update the ANTLR tool version and update lexer token names for consistency [#469]
    • Fix the panic in the codelab solution [#479]

    New Contributors

    • @sahil-madeka made their first contribution in https://github.com/google/cel-go/pull/480
    • @jpbetz made their first contribution in https://github.com/google/cel-go/pull/483

    Full Changelog: https://github.com/google/cel-go/compare/v0.9.0...v0.10.0

    Source code(tar.gz)
    Source code(zip)
  • v0.9.0(Oct 19, 2021)

    Features

    • Allow building the cel.Ast with a backing text source [#451]
    • Support for populating macro calls within the SourceInfo [#455]
    • Add unparsing support for macro calls [#458]

    Fixes

    • Ensure type-adaptation is used for planning constant values [#463]
    • Bug fixes for type-sanitization and abstract type support [#460]
    • Rename go_strings_library to go_default_library [#457]
    Source code(tar.gz)
    Source code(zip)
  • v0.8.0(Sep 18, 2021)

    Update with parser hardening and general improvements toward 100% conformance with the CEL-Spec.

    Features

    • [#430] Recursion limits and error recovery attempt limit parse-time options
    • [#433] Expression size limit parse-time option
    • [#443] Change recursion checks to be rule-based, to better match the spec
    • [#446] Make it to use a single proto message's fields as the basis for all CEL variables
    • [#447] Parser error recovery lookahead limit to prevent pathological backtracking

    Fixes

    • [#422] Return errors when duration or timestamp overflow is detected
    • [#423] Preserve subsecond precision when converting timestamps from strings
    • [#427] Use accessor methods for source info instead of fields directly to avoid panic
    • [#436] Fix the IsChecked call for constant expressions
    • [#439] Ensure RemoveErrorListeners() is called on lexer and parser objects allocated from pools.
    • [#448] Unify overflow checking in operators, field setting.
    • [#449] Fix list and map equality to preserve logical ANDing of elements

    Performance

    • [#426] Optimize the antlr.CharStream implementation
    Source code(tar.gz)
    Source code(zip)
  • v0.7.3(Mar 25, 2021)

    Minor release with some minor fixes to improve ease of use and safety of the library.

    Fixes

    • [#416] Support trailing commas in CreateMessage and CreateStruct expressions
    • [#421] Return errors when signed or unsigned integer overflow is detected
    • [#419] Fix infinite loop in AST prune
    Source code(tar.gz)
    Source code(zip)
  • v0.7.2(Feb 10, 2021)

    This release fixes minor gaps in the API between v0.6.0 and v0.7.*. Most users will be unaffected by these bugs, but they are common enough to warrant a point release.

    Fixes

    • [#414] Re-add support for duration and timestamp proto values as CEL Values.
    • [#413] Ensure that proto reflection falls back to dynamic lookup
    Source code(tar.gz)
    Source code(zip)
  • v0.7.1(Jan 29, 2021)

    Fixes

    • [#411] Ensure protodesc.FileDescriptor references are sourced from protoregistry.GlobalFiles when possible.

    Features

    • [#410] Expose type formatting utility in cel.FormatType()
    Source code(tar.gz)
    Source code(zip)
  • v0.7.0(Jan 13, 2021)

    Improvements

    [#399] Support for Protobuf Golang API v2.

    Fixes

    [#394] Update CheckedExprToAst utility to handle constant expressions. [#393] Update the conformance test version and Bazel build structure.

    Breaking Changes

    Value v. ConvertToNative

    Calling Value() on a proto-based object will likely return a *dynamicpb.Message instance rather than the strongly typed proto message. Using ConvertToNative(reflect.TypeOf(&<DesiredType>{}) will produce the desired result.

    DescriptorProto v. Descriptor

    Top-level interfaces have shifted away from using the DescriptorProto and FileDescriptorProto messages directly in favor of the protobuf v2 API protoreflect.Descriptor and protoreflect.FileDescriptor.

    Duration and Timestamp

    The duration.go and timestamp.go object types are now derived from go-native time.Duration and time.Time respectively as the dependence on the protobuf counterparts was not actually necessary.

    Source code(tar.gz)
    Source code(zip)
  • v0.6.0(Sep 22, 2020)

    Improvements

    • [#362] Expose interfaces that allow users to write their own CEL expression decorators.
    • [#360] Optimize type conversion functions, spot errors in timestamp and duration program plan time.
    • [#328] Publish the CEL-Go Codelab source.
    • [#372] Introduce upper / lower ASCII string functions.
    • [#373, #379] Introduce base64 encode / decode.
    • [#367] Aliased identifier support

    Fixes

    • [#361] Fix type map references for Attributes and id references within qualifiers.
    • [#375] Support hexidecimal int literals.
    • [#382] Support gogo protogen protos for better Kubernetes proto support.
    • [#384, #386] Fix Residual computations to be non-mutating.

    Breaking Changes

    Aliased identifier support introduces breaking changes by replacing the Packager concept with a Container to better match the CEL specification. See #367 for more information about the specific changes.

    Source code(tar.gz)
    Source code(zip)
  • v0.5.1(May 22, 2020)

    Fixes

    [#357] Implements timestamp(<unix_epoch>) which was supported in the checker, but not implemented.

    Features

    [#354] Introduces a feature flag mechanism for introducing new features behind flag guards.

    Source code(tar.gz)
    Source code(zip)
  • v0.5.0(May 8, 2020)

    Improvements

    • [#342] Introduced decls.NewVar and decls.NewConst as a replacement for decls.NewIdent
    • [#343] Parse and check errors are stable sorted by their source location.
    • [#348] Added sync.Pool in front of ANTLR lexer / parser to improve checker performance.

    Fixes

    • [#341] Support for namespaced functions. See Breaking Changes for more information before use.
    • [#345] Doc fix to remove reference to a removed evaluation option.

    Breaking Changes

    Support for namespaced function resolution means that CEL extension functions can now have qualified names, such as base64.encode. This has always been supported by the CEL type-checker and the CEL specification, but was never properly supported by the evaluators. As part of this fix, the type-checker introduces AST rewrites to ensure that all identifiers in the checked AST are fully-qualified. This change simplifies the execution planning phase for the program, but may introduce structural differences between v0.5+ ASTs and those created with prior releases of CEL.

    The structural difference introduced with this change should not affect evaluation. If anything v0.5+ ASTs will improve the conformance of the C++ evaluator with the CEL spec.

    Source code(tar.gz)
    Source code(zip)
  • v0.4.2(Apr 21, 2020)

    Fixes

    • Make the has() macro consistent with cel-spec for proto2 and proto3 message types.
    • Improve type resolution when there are multiple overloads with the same return type.
    • Remove shared state from the Env#Extend() call. #issues/333
    • Fix proto2 enum assignments during object constructions.
    • Make Attribute values Stringer implementations to make them human-readable in errors.

    Breaking Changes

    The Env#Extend() changes introduced a new method on the ref.TypeRegistry interface called Copy. If the user has implemented a custom TypeRegistry, the Copy method is required in order to support extension. If the TypeRegistry is immutable, it may trivially return itself.

    Source code(tar.gz)
    Source code(zip)
  • v0.4.1(Mar 26, 2020)

    Bug fix release to address issues introduced in v0.4.0

    Fixes

    • Enable support for index operations with global function calls as arguments #325
    • Ensure mutable shared state updates are appropriately synchronized #322
    Source code(tar.gz)
    Source code(zip)
  • v0.4.0(Feb 6, 2020)

    The v0.4.0 release of CEL-Go introduces several fixes, features, and breaking changes since v0.3.2.

    Features

    • Top-level support for partial evaluation
      • Mark attributes (either whole variables or parts of them) as unknown.
      • Generate residual ASTs from partial evaluations using cel.EvalDetails.
    • Replaced several top-level interfaces with concrete structs.
    • Simplified the embedding of CEL into larger languages, such as CEL Policy Templates.
    • Improved field selection and indexing performance by 10x for proto2 and proto3.
    • Introduced a new cel.Library interface and extension library for dealing with string manipulation.

    Fixes

    • Checker support for protobuf sfixed32, sfixed64 fields.
    • Convert certain type param resolution to dyn to prevent type resolution errors.
    • Disable short-circuiting in the exists_one macro to be consistent with CEL spec.
    • Remove dyn as a runtime type, and add it as an identity function dyn(<expr>) == expr.
    • Ensure strings must be valid unicode.
    • Remove support for!1 as a valid parse-only expression.
    • Fix recursive registration of imported proto files within a descriptor.
    • Enable proto supporting conformance tests.
    • Change the cel.AstToString function to behave like a single-line formatter.
    • Convert the text representation of byte literals to octal to be compatible with Google SQL.
    • Improved support for ConvertToNative for maps and lists.
    • Fix error propagation on !=.

    Breaking Changes

    • The cel.Issues, cel.Ast, cel.Env, and cel.EvalDetails interfaces have been replaced with concrete types.
    • The interpreter.NewAdaptingActivation and interpreter.AdaptingActivation have been replaced by automatic propagation and use of the ref.TypeAdapter during variable resolution.
    • The cel.Env construction will defer environment validation until the first env.Check call.
    • The Program.Eval(Activation) method will result in an error if a declared variable appears in the expression, but not in the activation. Use Env.UnknownActivation() and cel.EnvOptions(OptPartialEval) to achieve the same behavior.
    Source code(tar.gz)
    Source code(zip)
  • v0.4.0-alpha.2(Oct 30, 2019)

    Alpha release which improves the usability of CEL values. Another point release on the way toward v0.4.0.

    Features

    Improve type conversion capabilities for lists and maps.

    Source code(tar.gz)
    Source code(zip)
  • v0.4.0-alpha.1(Oct 25, 2019)

    This is an alpha release of the planned 0.4.0 release which will feature the following changes:

    • Replace a handful of top-level interfaces with concrete structs.
    • Complete the known unknowns implementation.
    • Making it easier to embed CEL in larger rule engines.

    The alpha releases will include breaking changes and bug fixes on the path to publishing the official 0.4.0 release.

    Features

    • Support for parsing from common.Source objects.
    • Ability to override the creation of common.Location objects at parse time.
    • Instances of common.Errors and cel.Issues may be merged together.
    • New test case showing how to use custom macros.

    Fixes

    • Fix for error propagation on != operations.
    • Fix for panic during type-check when the comprehension ranges are of invalid type.

    Breaking Changes

    • The common.Source interface removes the IDOffset and IDLocation methods and adds NewLocation
    • The cel.Issues interface has been replaced by a concrete struct type.
    Source code(tar.gz)
    Source code(zip)
  • v0.3.2(Oct 9, 2019)

  • v0.3.1(Oct 8, 2019)

    Fixes

    • The parser/unparser.go appropriately handles space-sensitive operators.
    • The interpreter/planner.go supports the overloading operations by overload id.
    • Support for wrapper, protobuf.Any, and Proto3 to JSON-based protobuf.Value conversions within ConvertToNative.
    • Support for iterating over the interpreter/evalstate.go values.
    • Removed a pathological recursion case from the type-checker.
    Source code(tar.gz)
    Source code(zip)
Owner
Google
Google ❤️ Open Source
Google
Expression evaluation in golang

Gval Gval (Go eVALuate) provides support for evaluating arbitrary expressions, in particular Go-like expressions. Evaluate Gval can evaluate expressio

null 558 Nov 23, 2022
A fast script language for Go

The Tengo Language Tengo is a small, dynamic, fast, secure script language for Go. Tengo is fast and secure because it's compiled/executed as bytecode

daniel 3k Nov 28, 2022
🦁 A Super fast and lightweight runtime for JavaScript Scripts

Kimera.js - A super fast and lightweight JavaScript Runtime for Scripts.

Eliaz Bobadilla 22 Aug 14, 2022
Fast, portable, non-Turing complete expression evaluation with gradual typing (Go)

Common Expression Language The Common Expression Language (CEL) is a non-Turing complete language designed for simplicity, speed, safety, and portabil

Google 1.4k Nov 29, 2022
Expression evaluation engine for Go: fast, non-Turing complete, dynamic typing, static typing

Expr Expr package provides an engine that can compile and evaluate expressions. An expression is a one-liner that returns a value (mostly, but not lim

Anton Medvedev 3.2k Dec 1, 2022
Expression evaluation engine for Go: fast, non-Turing complete, dynamic typing, static typing

Expr Expr package provides an engine that can compile and evaluate expressions. An expression is a one-liner that returns a value (mostly, but not lim

Anton Medvedev 3.2k Dec 6, 2022
Expression evaluation engine for Go: fast, non-Turing complete, dynamic typing, static typing

Expr Expr package provides an engine that can compile and evaluate expressions. An expression is a one-liner that returns a value (mostly, but not lim

Anton Medvedev 3.2k Nov 27, 2022
Go-turing-i2c-cmdline - Controlling the i2c management bus of the turing pi with i2c works fine

go-turing-i2c-cmdline What is it? Controlling the i2c management bus of the turi

null 2 Jan 24, 2022
poCo: portable Containers. Create statically linked, portable binaries from container images (daemonless)

poCo Containers -> Binaries Create statically linked, portable binaries from container images A simple, static golang bundler! poCo (portable-Containe

Ettore Di Giacinto 71 Oct 25, 2022
Expression evaluation in golang

Gval Gval (Go eVALuate) provides support for evaluating arbitrary expressions, in particular Go-like expressions. Evaluate Gval can evaluate expressio

null 558 Nov 23, 2022
Expression evaluation in golang

Gval Gval (Go eVALuate) provides support for evaluating arbitrary expressions, in particular Go-like expressions. Evaluate Gval can evaluate expressio

null 559 Nov 30, 2022
Arbitrary expression evaluation for golang

govaluate Provides support for evaluating arbitrary C-like artithmetic/string expressions. Why can't you just write these expressions in code? Sometim

George Lester 2.8k Nov 29, 2022
Simple expression evaluation engine for Go

??️ chili Currently in development, Unstable (API may change in future) Simple expression evaluation engine. Expression is one liner that evalutes int

Santhosh Kumar 71 Nov 8, 2022
An implementation of Neural Turing Machines

Neural Turing Machines Package ntm implements the Neural Turing Machine architecture as described in A.Graves, G. Wayne, and I. Danihelka. arXiv prepr

Fumin 398 Sep 13, 2022
A blazingly-fast simple-to-use tool to find duplicate files on your computer, portable hard drives etc.

A fast and simple tool to find duplicate files (photos, videos, music, documents) on your computer, portable hard drives etc.

Manu Manjunath 215 Nov 19, 2022
🚀Gev is a lightweight, fast non-blocking TCP network library based on Reactor mode. Support custom protocols to quickly and easily build high-performance servers.

gev 中文 | English gev is a lightweight, fast non-blocking TCP network library based on Reactor mode. Support custom protocols to quickly and easily bui

徐旭 1.5k Dec 5, 2022
A terminal based typing test.

What A terminal based typing test. Installation Linux sudo curl -L https://github.com/lemnos/tt/releases/download/v0.4.0/tt-linux -o /usr/local/bin/tt

null 417 Dec 6, 2022
Serverless SOAR (Security Orchestration, Automation and Response) framework for automatic inspection and evaluation of security alert

DeepAlert DeepAlert is a serverless framework for automatic response of security alert. Overview DeepAlert receives a security alert that is event of

null 35 Nov 9, 2022
Command line tool for improving typing skills (programmers friendly)

Command line tool for improving typing speed and accuracy. The main goal is to help programmers practise programming languages. Demo Installation Pyth

Jan 375 Dec 5, 2022
Typing test in your terminal

Typer Typing test in your terminal Installation go get github.com/maaslalani/typer/cmd/typer Usage To begin a typing test simply type typer. This wil

Maas Lalani 315 Dec 2, 2022