From 6171d560d7faf0513a2547542d92a9781a594100 Mon Sep 17 00:00:00 2001 From: Anton Medvedev Date: Wed, 8 May 2024 22:20:37 +0200 Subject: [PATCH] Update docs --- docs/configuration.md | 201 ++++++++++++++++------------------- docs/environment.md | 95 +++++++++++++++++ docs/functions.md | 86 +++++++++++++++ docs/getting-started.md | 90 +++++++++------- docs/images/debug.gif | Bin 3546095 -> 0 bytes docs/images/logo-small.png | Bin 86921 -> 0 bytes docs/images/logo.png | Bin 395487 -> 0 bytes docs/internals.md | 61 ----------- docs/language-definition.md | 2 +- docs/operator-overloading.md | 52 --------- docs/patch.md | 125 ++++++++++++++++++++++ docs/tips.md | 38 ------- docs/visitor-and-patch.md | 98 ----------------- docs/visitor.md | 49 +++++++++ 14 files changed, 495 insertions(+), 402 deletions(-) create mode 100644 docs/environment.md create mode 100644 docs/functions.md delete mode 100644 docs/images/debug.gif delete mode 100644 docs/images/logo-small.png delete mode 100644 docs/images/logo.png delete mode 100644 docs/internals.md delete mode 100644 docs/operator-overloading.md create mode 100644 docs/patch.md delete mode 100644 docs/tips.md delete mode 100644 docs/visitor-and-patch.md create mode 100644 docs/visitor.md diff --git a/docs/configuration.md b/docs/configuration.md index a427515e9..511ebd48b 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -1,156 +1,135 @@ # Configuration -Expr can be configured with options. For example, you can pass the environment with variables and functions. +## Return type -## AllowUndefinedVariables() +Usually, the return type of expression is anything. But we can instruct type checker to verify the return type of the +expression. +For example, in filter expressions, we expect the return type to be a boolean. -This option allows undefined variables in the expression. By default, Expr will return an error -if the expression contains undefined variables. +```go +program, err := expr.Compile(code, expr.AsBool()) +if err != nil { +panic(err) +} -```go -program, err := expr.Compile(`foo + bar`, expr.AllowUndefinedVariables()) -``` +output, err := expr.Run(program, env) +if err != nil { +panic(err) +} -## AsBool() +ok := output.(bool) // It is safe to assert the output to bool, if the expression is type checked as bool. +``` -This option forces the expression to return a boolean value. If the expression returns a non-boolean value, -Expr will return an error. +If `code` variable for example returns a string, the compiler will return an error. -```go -program, err := expr.Compile(`Title contains "Hello"`, expr.AsBool()) -``` +Expr has a few options to specify the return type: -## AsFloat64() +- [expr.AsBool()](https://pkg.go.dev/github.com/expr-lang/expr#AsBool) - expects the return type to be a bool. +- [expr.AsInt()](https://pkg.go.dev/github.com/expr-lang/expr#AsInt) - expects the return type to be an int (float64, + uint, int32, and other will be cast to int). +- [expr.AsInt64()](https://pkg.go.dev/github.com/expr-lang/expr#AsInt64) - expects the return type to be an int64 ( + float64, uint, int32, and other will be cast to int64). +- [expr.AsFloat64()](https://pkg.go.dev/github.com/expr-lang/expr#AsFloat64) - expects the return type to be a float64 ( + float32 will be cast to float64). +- [expr.AsAny()](https://pkg.go.dev/github.com/expr-lang/expr#AsAny) - expects the return type to be anything. +- [expr.AsKind(reflect.Kind)](https://pkg.go.dev/github.com/expr-lang/expr#AsKind) - expects the return type to be a + specific kind. -This option forces the expression to return a float64 value. If the expression returns a non-float64 value, -Expr will return an error. +:::tip Warn on any +By default, type checker will accept any type, even if the return type is specified. Consider following examples: -```go -program, err := expr.Compile(`42`, expr.AsFloat64()) +```expr +let arr = [1, 2, 3]; arr[0] ``` -:::note -If the expression returns integer value, Expr will convert it to float64. -::: - -## AsInt() +The return type of the expression is `any`. Arrays created in Expr are of type `[]any`. The type checker will not return +an error if the return type is specified as `expr.AsInt()`. The output of the expression is `1`, which is an int, but the +type checker will not return an error. -This option forces the expression to return an int value. If the expression returns a non-int value, -Expr will return an error. +But we can instruct the type checker to warn us if the return type is `any`. Use [`expr.WarnOnAny()`](https://pkg.go.dev/github.com/expr-lang/expr#WarnOnAny) to enable this behavior. ```go -program, err := expr.Compile(`42`, expr.AsInt()) +program, err := expr.Compile(code, expr.AsInt(), expr.WarnOnAny()) ``` -:::note -If the expression returns a float value, Expr truncates it to int. -::: - -## AsInt64() +The type checker will return an error if the return type is `any`. We need to modify the expression to return a specific +type. -Same as `AsInt()` but returns an int64 value. - -```go -program, err := expr.Compile(`42`, expr.AsInt64()) +```expr +let arr = [1, 2, 3]; int(arr[0]) ``` +::: -## AsKind() -This option forces the expression to return a value of the specified kind. -If the expression returns a value of a different kind, Expr will return an error. +## WithContext -```go -program, err := expr.Compile(`42`, expr.AsKind(reflect.String)) -``` +Although the compiled program is guaranteed to be terminated, some user defined functions may not be. For example, if a +user defined function calls a remote service, we may want to pass a context to the function. -## ConstExpr() +This is possible via the [`WithContext`](https://pkg.go.dev/github.com/expr-lang/expr#WithContext) option. -This option tells Expr to treat specified functions as constant expressions. -If all arguments of the function are constants, Expr will replace the function call with the result -during the compile step. +This option will modify function calls to include the context as the first argument (only if the function signature +accepts a context). -```go -program, err := expr.Compile(`fib(42)`, expr.ConstExpr("fib")) +```expr +customFunc(42) +// will be transformed to +customFunc(ctx, 42) ``` -[ConstExpr Example](https://pkg.go.dev/github.com/expr-lang/expr?tab=doc#ConstExpr) - -## Env() - -This option passes the environment with variables and functions to the expression. +Function `expr.WithContext()` takes the name of context variable. The context variable must be defined in the environment. ```go -program, err := expr.Compile(`foo + bar`, expr.Env(Env{})) +env := map[string]any{ + "ctx": context.Background(), +} + +program, err := expr.Compile(code, expr.Env(env), expr.WithContext("ctx")) ``` -## Function() +## ConstExpr -This option adds a function to the expression. +For some user defined functions, we may want to evaluate the expression at compile time. This is possible via the +[`ConstExpr`](https://pkg.go.dev/github.com/expr-lang/expr#ConstExpr) option. ```go - atoi := expr.Function( - "atoi", - func(params ...any) (any, error) { - return strconv.Atoi(params[0].(string)) - }, - ) - - program, err := expr.Compile(`atoi("42")`, atoi) +func fib(n int) int { + if n <= 1 { + return n + } + return fib(n-1) + fib(n-2) +} + +env := map[string]any{ + "fib": fib, +} + +program, err := expr.Compile(`fib(10)`, expr.Env(env), expr.ConstExpr("fib")) ``` -Expr sees the `atoi` function as a function with a variadic number of arguments of type `any` and returns a value of type `any`. But, we can specify the types of arguments and the return value by adding the correct function -signature or multiple signatures. +If all arguments of the function are constants, the function will be evaluated at compile time. The result of the function +will be used as a constant in the expression. -```go - atoi := expr.Function( - "atoi", - func(params ...any) (any, error) { - return strconv.Atoi(params[0].(string)) - }, - new(func(string) int), - ) +```expr +fib(10) // will be transformed to 55 during the compilation +fib(12+12) // will be transformed to 267914296 during the compilation +fib(x) // will **not** be transformed and will be evaluated at runtime ``` -Or we can simply reuse the `strconv.Atoi` function. - -```go - atoi := expr.Function( - "atoi", - func(params ...any) (any, error) { - return strconv.Atoi(params[0].(string)) - }, - strconv.Atoi, - ) -``` +## Options -Here is another example with a few function signatures: +Compiler options can be defined as an array: ```go - toInt := expr.Function( - "toInt", - func(params ...any) (any, error) { - switch params[0].(type) { - case float64: - return int(params[0].(float64)), nil - case string: - return strconv.Atoi(params[0].(string)) - } - return nil, fmt.Errorf("invalid type") - }, - new(func(float64) int), - new(func(string) int), - ) +options := []expr.Option{ + expr.Env(Env{}) + expr.AsInt(), + expr.WarnOnAny(), + expr.WithContext("ctx"), + expr.ConstExpr("fib"), +} + +program, err := expr.Compile(code, options...) ``` - -## Operator() - -This options defines an [operator overloading](operator-overloading). - -## Optimize() - -This option enables [optimizations](internals.md). By default, Expr will optimize the expression. - -## Patch() - -This option allows you to [patch the expression](visitor-and-patch) before compilation. +Full list of available options can be found in the [pkg.go.dev](https://pkg.go.dev/github.com/expr-lang/expr#Option) documentation. diff --git a/docs/environment.md b/docs/environment.md new file mode 100644 index 000000000..2ae2f0af6 --- /dev/null +++ b/docs/environment.md @@ -0,0 +1,95 @@ +# Environment + +The environment is a map or a struct that contains the variables and functions that the expression can access. + +## Struct as Environment + +Let's consider the following example: + +```go +type Env struct { + UpdatedAt time.Time + Posts []Post + Map map[string]string `expr:"tags"` +} +``` + +The `Env` struct contains 3 variables that the expression can access: `UpdatedAt`, `Posts`, and `tags`. + +:::info +The `expr` tag is used to rename the `Map` field to `tags` variable in the expression. +::: + +The `Env` struct can also contain methods. The methods defined on the struct become functions that the expression can +call. + +```go +func (Env) Format(t time.Time) string { + return t.Format(time.RFC822) +} +``` + +:::tip +Methods defined on embedded structs are also accessible. +```go +type Env struct { + Helpers +} + +type Helpers struct{} + +func (Helpers) Format(t time.Time) string { + return t.Format(time.RFC822) +} +``` +::: + +We can use an empty struct `Env{}` to with [expr.Env](https://pkg.go.dev/github.com/expr-lang/expr#Env) to create an environment. Expr will use reflection to find +the fields and methods of the struct. + +```go +program, err := expr.Compile(code, expr.Env(Env{})) +``` + +Compiler will type check the expression against the environment. After the compilation, we can run the program with the environment. +You should use the same type of environment that you passed to the `expr.Env` function. + +```go +output, err := expr.Run(program, Env{ + UpdatedAt: time.Now(), + Posts: []Post{{Title: "Hello, World!"}}, + Map: map[string]string{"tag1": "value1"}, +}) +``` + +## Map as Environment + +You can also use a map as an environment. + +```go +env := map[string]any{ + "UpdatedAt": time.Time{}, + "Posts": []Post{}, + "tags": map[string]string{}, + "sprintf": fmt.Sprintf, +} + +program, err := expr.Compile(code, expr.Env(env)) +``` + +A map defines variables and functions that the expression can access. The key is the variable name, and the type +is the value's type. + +```go +env := map[string]any{ + "object": map[string]any{ + "field": 42, + }, +} +``` + +Expr will infer the type of the `object` variable as `map[string]any`. + +By default, Expr will return an error if unknown variables are used in the expression. + +You can disable this behavior by passing [`AllowUndefinedVariables`](https://pkg.go.dev/github.com/expr-lang/expr#AllowUndefinedVariables) option to the compiler. diff --git a/docs/functions.md b/docs/functions.md new file mode 100644 index 000000000..03b5b9641 --- /dev/null +++ b/docs/functions.md @@ -0,0 +1,86 @@ +# Functions + +Expr comes with a set of [builtin](language-definition.md) functions, but you can also define your own functions. + +The easiest way to define a custom function is to add it to the environment. + +```go +env := map[string]any{ + "add": func(a, b int) int { + return a + b + }, +} +``` + +Or you can use functions defined on a struct: + +```go +type Env struct{} + +func (Env) Add(a, b int) int { + return a + b +} +``` + +:::info +If functions are marked with [`ConstExpr`](./configuration.md#constexpr) option, they will be evaluated at compile time. +::: + +The best way to define a function from a performance perspective is to use a [`Function`](https://pkg.go.dev/github.com/expr-lang/expr#Function) option. + +```go +atoi := expr.Function( + "atoi", + func(params ...any) (any, error) { + return strconv.Atoi(params[0].(string)) + }, +) + +program, err := expr.Compile(`atoi("42")`, atoi) +``` + +Type checker sees the `atoi` function as a function with a variadic number of arguments of type `any`, and returns +a value of type `any`. But, we can specify the types of arguments and the return value by adding the correct function +signature or multiple signatures. + +```go +atoi := expr.Function( + "atoi", + func(params ...any) (any, error) { + return strconv.Atoi(params[0].(string)) + }, + new(func(string) int), +) +``` + +Or we can simply reuse the strconv.Atoi function as a type: + +```go +atoi := expr.Function( + "atoi", + func(params ...any) (any, error) { + return strconv.Atoi(params[0].(string)) + }, + // highlight-next-line + strconv.Atoi, +) +``` + +It is possible to define multiple signatures for a function: + +```go +toInt := expr.Function( + "toInt", + func(params ...any) (any, error) { + switch params[0].(type) { + case float64: + return int(params[0].(float64)), nil + case string: + return strconv.Atoi(params[0].(string)) + } + return nil, fmt.Errorf("invalid type") + }, + new(func(float64) int), + new(func(string) int), +) +``` diff --git a/docs/getting-started.md b/docs/getting-started.md index b6b0e4da9..8ee14fd49 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -26,20 +26,24 @@ fmt.Print(output) // 4 ``` Expr compiles the expression `2 + 2` into a bytecode program. Then we run -the program and get the output. The output is `4` as expected. +the program and get the output. + +:::tip +In performance-critical applications, you can reuse the compiled program. Compiled programs are safe for concurrent use. +**Compile once** and run **multiple** times. +::: + +The `expr.Compile` function returns a `*vm.Program` and an error. The `expr.Run` function takes a program and an +environment. The environment is a map of variables that can be used in the expression. In this example, we use `nil` as +an environment because we don't need any variables. -The `expr.Compile` function returns a `*vm.Program` and an error. The program -can be reused between runs. The `expr.Run` function takes a program and an -environment. The environment is a map of variables that can be used in the -expression. In this example, we use `nil` as an environment because we don't -need any variables. Now let's pass some variables to the expression: ```go env := map[string]any{ "foo": 100, - "bar": 200, + "bar": 200, } program, err := expr.Compile(`foo + bar`, expr.Env(env)) @@ -56,7 +60,9 @@ fmt.Print(output) // 300 ``` Why do we need to pass the environment to the `expr.Compile` function? Expr can be used as a type-safe language. -Expr can infer the type of the expression and check it against the environment. Here is an example: +Expr can infer the type of the expression and check it against the environment. + +Here is an example: ```go env := map[string]any{ @@ -70,73 +76,75 @@ if err != nil { } ``` -Expr can work with any Go types. Here is an example: +Expr can work with any Go types: ```go env := map[string]any{ - "greet": "Hello, %v!", - "names": []string{"world", "you"}, - "sprintf": fmt.Sprintf, + "greet": "Hello, %v!", + "names": []string{"world", "you"}, + "sprintf": fmt.Sprintf, } code := `sprintf(greet, names[0])` program, err := expr.Compile(code, expr.Env(env)) if err != nil { - panic(err) + panic(err) } output, err := expr.Run(program, env) if err != nil { - panic(err) + panic(err) } fmt.Print(output) // Hello, world! ``` Also, Expr can use a struct as an environment. Methods defined on the struct become functions. -The struct fields can be renamed with the `expr` tag. Here is an example: +The struct fields can be renamed with the `expr` tag. + +Here is an example: ```go type Env struct { - Posts []Post `expr:"posts"` + Posts []Post `expr:"posts"` } func (Env) Format(t time.Time) string { - return t.Format(time.RFC822) + return t.Format(time.RFC822) } type Post struct { - Body string - Date time.Time + Body string + Date time.Time } func main() { - code := `map(posts, Format(.Date) + ": " + .Body)` - - program, err := expr.Compile(code, expr.Env(Env{})) - if err != nil { - panic(err) - } - - env := Env{ - Posts: []Post{ - {"Oh My God!", time.Now()}, - {"How you doin?", time.Now()}, - {"Could I be wearing any more clothes?", time.Now()}, - }, - } - - output, err := expr.Run(program, env) - if err != nil { - panic(err) - } - - fmt.Print(output) + code := `map(posts, Format(.Date) + ": " + .Body)` + + program, err := expr.Compile(code, expr.Env(Env{})) + if err != nil { + panic(err) + } + + env := Env{ + Posts: []Post{ + {"Oh My God!", time.Now()}, + {"How you doin?", time.Now()}, + {"Could I be wearing any more clothes?", time.Now()}, + }, + } + + output, err := expr.Run(program, env) + if err != nil { + panic(err) + } + + fmt.Print(output) } ``` -The compiled program can be reused between runs. Here is an example: +The compiled program can be reused between runs. ```go type Env struct { diff --git a/docs/images/debug.gif b/docs/images/debug.gif deleted file mode 100644 index 90a6ec2e6c9d0d708ccf2d069934fce9b8775550..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3546095 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