add Eval function (#338)
This commit is contained in:
parent
50af716288
commit
ac805806f8
3 changed files with 114 additions and 10 deletions
26
README.md
26
README.md
|
@ -4,7 +4,7 @@
|
|||
|
||||
# The Tengo Language
|
||||
|
||||
[![GoDoc](https://godoc.org/github.com/d5/tengo?status.svg)](https://godoc.org/github.com/d5/tengo)
|
||||
[![GoDoc](https://godoc.org/github.com/d5/tengo/v2?status.svg)](https://godoc.org/github.com/d5/tengo/v2)
|
||||
![test](https://github.com/d5/tengo/workflows/test/badge.svg)
|
||||
[![Go Report Card](https://goreportcard.com/badge/github.com/d5/tengo)](https://goreportcard.com/report/github.com/d5/tengo)
|
||||
|
||||
|
@ -93,9 +93,9 @@ import (
|
|||
)
|
||||
|
||||
func main() {
|
||||
// Tengo script code
|
||||
src := `
|
||||
each := func(seq, fn) {
|
||||
// create a new Script instance
|
||||
script := tengo.NewScript([]byte(
|
||||
`each := func(seq, fn) {
|
||||
for x in seq { fn(x) }
|
||||
}
|
||||
|
||||
|
@ -104,10 +104,7 @@ mul := 1
|
|||
each([a, b, c, d], func(x) {
|
||||
sum += x
|
||||
mul *= x
|
||||
})`
|
||||
|
||||
// create a new Script instance
|
||||
script := tengo.NewScript([]byte(src))
|
||||
})`))
|
||||
|
||||
// set values
|
||||
_ = script.Add("a", 1)
|
||||
|
@ -128,6 +125,19 @@ each([a, b, c, d], func(x) {
|
|||
}
|
||||
```
|
||||
|
||||
Or, if you need to evaluate a simple expression, you can use [Eval](https://pkg.go.dev/github.com/d5/tengo/v2#Eval) function instead:
|
||||
|
||||
|
||||
```golang
|
||||
res, err := tengo.Eval(ctx,
|
||||
`input ? "success" : "fail"`,
|
||||
map[string]interface{}{"input": 1})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println(res) // "success"
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- [Language Syntax](https://github.com/d5/tengo/blob/master/docs/tutorial.md)
|
||||
|
|
35
eval.go
Normal file
35
eval.go
Normal file
|
@ -0,0 +1,35 @@
|
|||
package tengo
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Eval compiles and executes given expr with params, and returns an
|
||||
// evaluated value. expr must be an expression. Otherwise it will fail to
|
||||
// compile. Expression must not use or define variable "__res__" as it's
|
||||
// reserved for the internal usage.
|
||||
func Eval(
|
||||
ctx context.Context,
|
||||
expr string,
|
||||
params map[string]interface{},
|
||||
) (interface{}, error) {
|
||||
expr = strings.TrimSpace(expr)
|
||||
if expr == "" {
|
||||
return nil, fmt.Errorf("empty expression")
|
||||
}
|
||||
|
||||
script := NewScript([]byte(fmt.Sprintf("__res__ := (%s)", expr)))
|
||||
for pk, pv := range params {
|
||||
err := script.Add(pk, pv)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("script add: %w", err)
|
||||
}
|
||||
}
|
||||
compiled, err := script.RunContext(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("script run: %w", err)
|
||||
}
|
||||
return compiled.Get("__res__").Value(), nil
|
||||
}
|
59
eval_test.go
Normal file
59
eval_test.go
Normal file
|
@ -0,0 +1,59 @@
|
|||
package tengo_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/d5/tengo/v2"
|
||||
"github.com/d5/tengo/v2/require"
|
||||
)
|
||||
|
||||
func TestEval(t *testing.T) {
|
||||
eval := func(
|
||||
expr string,
|
||||
params map[string]interface{},
|
||||
expected interface{},
|
||||
) {
|
||||
ctx := context.Background()
|
||||
actual, err := tengo.Eval(ctx, expr, params)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expected, actual)
|
||||
}
|
||||
|
||||
eval(`undefined`, nil, nil)
|
||||
eval(`1`, nil, int64(1))
|
||||
eval(`19 + 23`, nil, int64(42))
|
||||
eval(`"foo bar"`, nil, "foo bar")
|
||||
eval(`[1, 2, 3][1]`, nil, int64(2))
|
||||
|
||||
eval(
|
||||
`5 + p`,
|
||||
map[string]interface{}{
|
||||
"p": 7,
|
||||
},
|
||||
int64(12),
|
||||
)
|
||||
eval(
|
||||
`"seven is " + p`,
|
||||
map[string]interface{}{
|
||||
"p": 7,
|
||||
},
|
||||
"seven is 7",
|
||||
)
|
||||
eval(
|
||||
`"" + a + b`,
|
||||
map[string]interface{}{
|
||||
"a": 7,
|
||||
"b": " is seven",
|
||||
},
|
||||
"7 is seven",
|
||||
)
|
||||
|
||||
eval(
|
||||
`a ? "success" : "fail"`,
|
||||
map[string]interface{}{
|
||||
"a": 1,
|
||||
},
|
||||
"success",
|
||||
)
|
||||
}
|
Loading…
Reference in a new issue