|
1 | 1 | # Configuration
|
2 | 2 |
|
3 |
| -Expr can be configured with options. For example, you can pass the environment with variables and functions. |
| 3 | +## Return type |
4 | 4 |
|
5 |
| -## AllowUndefinedVariables() |
| 5 | +Usually, the return type of expression is anything. But we can instruct type checker to verify the return type of the |
| 6 | +expression. |
| 7 | +For example, in filter expressions, we expect the return type to be a boolean. |
6 | 8 |
|
7 |
| -This option allows undefined variables in the expression. By default, Expr will return an error |
8 |
| -if the expression contains undefined variables. |
| 9 | +```go |
| 10 | +program, err := expr.Compile(code, expr.AsBool()) |
| 11 | +if err != nil { |
| 12 | +panic(err) |
| 13 | +} |
9 | 14 |
|
10 |
| -```go |
11 |
| -program, err := expr.Compile(`foo + bar`, expr.AllowUndefinedVariables()) |
12 |
| -``` |
| 15 | +output, err := expr.Run(program, env) |
| 16 | +if err != nil { |
| 17 | +panic(err) |
| 18 | +} |
13 | 19 |
|
14 |
| -## AsBool() |
| 20 | +ok := output.(bool) // It is safe to assert the output to bool, if the expression is type checked as bool. |
| 21 | +``` |
15 | 22 |
|
16 |
| -This option forces the expression to return a boolean value. If the expression returns a non-boolean value, |
17 |
| -Expr will return an error. |
| 23 | +If `code` variable for example returns a string, the compiler will return an error. |
18 | 24 |
|
19 |
| -```go |
20 |
| -program, err := expr.Compile(`Title contains "Hello"`, expr.AsBool()) |
21 |
| -``` |
| 25 | +Expr has a few options to specify the return type: |
22 | 26 |
|
23 |
| -## AsFloat64() |
| 27 | +- [expr.AsBool()](https://pkg.go.dev/github.com/expr-lang/expr#AsBool) - expects the return type to be a bool. |
| 28 | +- [expr.AsInt()](https://pkg.go.dev/github.com/expr-lang/expr#AsInt) - expects the return type to be an int (float64, |
| 29 | + uint, int32, and other will be cast to int). |
| 30 | +- [expr.AsInt64()](https://pkg.go.dev/github.com/expr-lang/expr#AsInt64) - expects the return type to be an int64 ( |
| 31 | + float64, uint, int32, and other will be cast to int64). |
| 32 | +- [expr.AsFloat64()](https://pkg.go.dev/github.com/expr-lang/expr#AsFloat64) - expects the return type to be a float64 ( |
| 33 | + float32 will be cast to float64). |
| 34 | +- [expr.AsAny()](https://pkg.go.dev/github.com/expr-lang/expr#AsAny) - expects the return type to be anything. |
| 35 | +- [expr.AsKind(reflect.Kind)](https://pkg.go.dev/github.com/expr-lang/expr#AsKind) - expects the return type to be a |
| 36 | + specific kind. |
24 | 37 |
|
25 |
| -This option forces the expression to return a float64 value. If the expression returns a non-float64 value, |
26 |
| -Expr will return an error. |
| 38 | +:::tip Warn on any |
| 39 | +By default, type checker will accept any type, even if the return type is specified. Consider following examples: |
27 | 40 |
|
28 |
| -```go |
29 |
| -program, err := expr.Compile(`42`, expr.AsFloat64()) |
| 41 | +```expr |
| 42 | +let arr = [1, 2, 3]; arr[0] |
30 | 43 | ```
|
31 | 44 |
|
32 |
| -:::note |
33 |
| -If the expression returns integer value, Expr will convert it to float64. |
34 |
| -::: |
35 |
| - |
36 |
| -## AsInt() |
| 45 | +The return type of the expression is `any`. Arrays created in Expr are of type `[]any`. The type checker will not return |
| 46 | +an error if the return type is specified as `expr.AsInt()`. The output of the expression is `1`, which is an int, but the |
| 47 | +type checker will not return an error. |
37 | 48 |
|
38 |
| -This option forces the expression to return an int value. If the expression returns a non-int value, |
39 |
| -Expr will return an error. |
| 49 | +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. |
40 | 50 |
|
41 | 51 | ```go
|
42 |
| -program, err := expr.Compile(`42`, expr.AsInt()) |
| 52 | +program, err := expr.Compile(code, expr.AsInt(), expr.WarnOnAny()) |
43 | 53 | ```
|
44 | 54 |
|
45 |
| -:::note |
46 |
| -If the expression returns a float value, Expr truncates it to int. |
47 |
| -::: |
48 |
| - |
49 |
| -## AsInt64() |
| 55 | +The type checker will return an error if the return type is `any`. We need to modify the expression to return a specific |
| 56 | +type. |
50 | 57 |
|
51 |
| -Same as `AsInt()` but returns an int64 value. |
52 |
| - |
53 |
| -```go |
54 |
| -program, err := expr.Compile(`42`, expr.AsInt64()) |
| 58 | +```expr |
| 59 | +let arr = [1, 2, 3]; int(arr[0]) |
55 | 60 | ```
|
| 61 | +::: |
56 | 62 |
|
57 |
| -## AsKind() |
58 | 63 |
|
59 |
| -This option forces the expression to return a value of the specified kind. |
60 |
| -If the expression returns a value of a different kind, Expr will return an error. |
| 64 | +## WithContext |
61 | 65 |
|
62 |
| -```go |
63 |
| -program, err := expr.Compile(`42`, expr.AsKind(reflect.String)) |
64 |
| -``` |
| 66 | +Although the compiled program is guaranteed to be terminated, some user defined functions may not be. For example, if a |
| 67 | +user defined function calls a remote service, we may want to pass a context to the function. |
65 | 68 |
|
66 |
| -## ConstExpr() |
| 69 | +This is possible via the [`WithContext`](https://pkg.go.dev/github.com/expr-lang/expr#WithContext) option. |
67 | 70 |
|
68 |
| -This option tells Expr to treat specified functions as constant expressions. |
69 |
| -If all arguments of the function are constants, Expr will replace the function call with the result |
70 |
| -during the compile step. |
| 71 | +This option will modify function calls to include the context as the first argument (only if the function signature |
| 72 | +accepts a context). |
71 | 73 |
|
72 |
| -```go |
73 |
| -program, err := expr.Compile(`fib(42)`, expr.ConstExpr("fib")) |
| 74 | +```expr |
| 75 | +customFunc(42) |
| 76 | +// will be transformed to |
| 77 | +customFunc(ctx, 42) |
74 | 78 | ```
|
75 | 79 |
|
76 |
| -[ConstExpr Example](https://pkg.go.dev/github.com/expr-lang/expr?tab=doc#ConstExpr) |
77 |
| - |
78 |
| -## Env() |
79 |
| - |
80 |
| -This option passes the environment with variables and functions to the expression. |
| 80 | +Function `expr.WithContext()` takes the name of context variable. The context variable must be defined in the environment. |
81 | 81 |
|
82 | 82 | ```go
|
83 |
| -program, err := expr.Compile(`foo + bar`, expr.Env(Env{})) |
| 83 | +env := map[string]any{ |
| 84 | + "ctx": context.Background(), |
| 85 | +} |
| 86 | + |
| 87 | +program, err := expr.Compile(code, expr.Env(env), expr.WithContext("ctx")) |
84 | 88 | ```
|
85 | 89 |
|
86 |
| -## Function() |
| 90 | +## ConstExpr |
87 | 91 |
|
88 |
| -This option adds a function to the expression. |
| 92 | +For some user defined functions, we may want to evaluate the expression at compile time. This is possible via the |
| 93 | +[`ConstExpr`](https://pkg.go.dev/github.com/expr-lang/expr#ConstExpr) option. |
89 | 94 |
|
90 | 95 | ```go
|
91 |
| - atoi := expr.Function( |
92 |
| - "atoi", |
93 |
| - func(params ...any) (any, error) { |
94 |
| - return strconv.Atoi(params[0].(string)) |
95 |
| - }, |
96 |
| - ) |
97 |
| - |
98 |
| - program, err := expr.Compile(`atoi("42")`, atoi) |
| 96 | +func fib(n int) int { |
| 97 | + if n <= 1 { |
| 98 | + return n |
| 99 | + } |
| 100 | + return fib(n-1) + fib(n-2) |
| 101 | +} |
| 102 | + |
| 103 | +env := map[string]any{ |
| 104 | + "fib": fib, |
| 105 | +} |
| 106 | + |
| 107 | +program, err := expr.Compile(`fib(10)`, expr.Env(env), expr.ConstExpr("fib")) |
99 | 108 | ```
|
100 | 109 |
|
101 |
| -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 |
102 |
| -signature or multiple signatures. |
| 110 | +If all arguments of the function are constants, the function will be evaluated at compile time. The result of the function |
| 111 | +will be used as a constant in the expression. |
103 | 112 |
|
104 |
| -```go |
105 |
| - atoi := expr.Function( |
106 |
| - "atoi", |
107 |
| - func(params ...any) (any, error) { |
108 |
| - return strconv.Atoi(params[0].(string)) |
109 |
| - }, |
110 |
| - new(func(string) int), |
111 |
| - ) |
| 113 | +```expr |
| 114 | +fib(10) // will be transformed to 55 during the compilation |
| 115 | +fib(12+12) // will be transformed to 267914296 during the compilation |
| 116 | +fib(x) // will **not** be transformed and will be evaluated at runtime |
112 | 117 | ```
|
113 | 118 |
|
114 |
| -Or we can simply reuse the `strconv.Atoi` function. |
115 |
| - |
116 |
| -```go |
117 |
| - atoi := expr.Function( |
118 |
| - "atoi", |
119 |
| - func(params ...any) (any, error) { |
120 |
| - return strconv.Atoi(params[0].(string)) |
121 |
| - }, |
122 |
| - strconv.Atoi, |
123 |
| - ) |
124 |
| -``` |
| 119 | +## Options |
125 | 120 |
|
126 |
| -Here is another example with a few function signatures: |
| 121 | +Compiler options can be defined as an array: |
127 | 122 |
|
128 | 123 | ```go
|
129 |
| - toInt := expr.Function( |
130 |
| - "toInt", |
131 |
| - func(params ...any) (any, error) { |
132 |
| - switch params[0].(type) { |
133 |
| - case float64: |
134 |
| - return int(params[0].(float64)), nil |
135 |
| - case string: |
136 |
| - return strconv.Atoi(params[0].(string)) |
137 |
| - } |
138 |
| - return nil, fmt.Errorf("invalid type") |
139 |
| - }, |
140 |
| - new(func(float64) int), |
141 |
| - new(func(string) int), |
142 |
| - ) |
| 124 | +options := []expr.Option{ |
| 125 | + expr.Env(Env{}) |
| 126 | + expr.AsInt(), |
| 127 | + expr.WarnOnAny(), |
| 128 | + expr.WithContext("ctx"), |
| 129 | + expr.ConstExpr("fib"), |
| 130 | +} |
| 131 | + |
| 132 | +program, err := expr.Compile(code, options...) |
143 | 133 | ```
|
144 | 134 |
|
145 |
| - |
146 |
| -## Operator() |
147 |
| - |
148 |
| -This options defines an [operator overloading](operator-overloading). |
149 |
| - |
150 |
| -## Optimize() |
151 |
| - |
152 |
| -This option enables [optimizations](internals.md). By default, Expr will optimize the expression. |
153 |
| - |
154 |
| -## Patch() |
155 |
| - |
156 |
| -This option allows you to [patch the expression](visitor-and-patch) before compilation. |
| 135 | +Full list of available options can be found in the [pkg.go.dev](https://pkg.go.dev/github.com/expr-lang/expr#Option) documentation. |
0 commit comments