|
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