Skip to content

Commit c85bc3b

Browse files
committed
Make expr.Eval faster
1 parent 3a0a1da commit c85bc3b

File tree

5 files changed

+47
-11
lines changed

5 files changed

+47
-11
lines changed

bench_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,26 @@ func Benchmark_expr(b *testing.B) {
3131
require.True(b, out.(bool))
3232
}
3333

34+
func Benchmark_expr_eval(b *testing.B) {
35+
params := make(map[string]any)
36+
params["Origin"] = "MOW"
37+
params["Country"] = "RU"
38+
params["Adults"] = 1
39+
params["Value"] = 100
40+
41+
var out any
42+
var err error
43+
44+
b.ResetTimer()
45+
for n := 0; n < b.N; n++ {
46+
out, err = expr.Eval(`(Origin == "MOW" || Country == "RU") && (Value >= 100 || Adults == 1)`, params)
47+
}
48+
b.StopTimer()
49+
50+
require.NoError(b, err)
51+
require.True(b, out.(bool))
52+
}
53+
3454
func Benchmark_expr_reuseVm(b *testing.B) {
3555
params := make(map[string]any)
3656
params["Origin"] = "MOW"

builtin/builtin_test.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -246,9 +246,15 @@ func TestBuiltin_errors(t *testing.T) {
246246
}
247247
for _, test := range errorTests {
248248
t.Run(test.input, func(t *testing.T) {
249-
_, err := expr.Eval(test.input, nil)
250-
assert.Error(t, err)
251-
assert.Contains(t, err.Error(), test.err)
249+
program, err := expr.Compile(test.input)
250+
if err != nil {
251+
assert.Error(t, err)
252+
assert.Contains(t, err.Error(), test.err)
253+
} else {
254+
_, err = expr.Run(program, nil)
255+
assert.Error(t, err)
256+
assert.Contains(t, err.Error(), test.err)
257+
}
252258
})
253259
}
254260
}

compiler/compiler.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -776,12 +776,16 @@ func (c *compiler) CallNode(node *ast.CallNode) {
776776
}
777777
c.compile(node.Callee)
778778

779-
isMethod, _, _ := checker.MethodIndex(c.config.Env, node.Callee)
780-
if index, ok := checker.TypedFuncIndex(node.Callee.Type(), isMethod); ok {
781-
c.emit(OpCallTyped, index)
782-
return
783-
} else if checker.IsFastFunc(node.Callee.Type(), isMethod) {
784-
c.emit(OpCallFast, len(node.Arguments))
779+
if c.config != nil {
780+
isMethod, _, _ := checker.MethodIndex(c.config.Env, node.Callee)
781+
if index, ok := checker.TypedFuncIndex(node.Callee.Type(), isMethod); ok {
782+
c.emit(OpCallTyped, index)
783+
return
784+
} else if checker.IsFastFunc(node.Callee.Type(), isMethod) {
785+
c.emit(OpCallFast, len(node.Arguments))
786+
} else {
787+
c.emit(OpCall, len(node.Arguments))
788+
}
785789
} else {
786790
c.emit(OpCall, len(node.Arguments))
787791
}

expr.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/expr-lang/expr/conf"
1414
"github.com/expr-lang/expr/file"
1515
"github.com/expr-lang/expr/optimizer"
16+
"github.com/expr-lang/expr/parser"
1617
"github.com/expr-lang/expr/patcher"
1718
"github.com/expr-lang/expr/vm"
1819
)
@@ -240,7 +241,12 @@ func Eval(input string, env any) (any, error) {
240241
return nil, fmt.Errorf("misused expr.Eval: second argument (env) should be passed without expr.Env")
241242
}
242243

243-
program, err := Compile(input)
244+
tree, err := parser.Parse(input)
245+
if err != nil {
246+
return nil, err
247+
}
248+
249+
program, err := compiler.Compile(tree, nil)
244250
if err != nil {
245251
return nil, err
246252
}

expr_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1684,7 +1684,7 @@ func TestEval_exposed_error(t *testing.T) {
16841684

16851685
fileError, ok := err.(*file.Error)
16861686
require.True(t, ok, "error should be of type *file.Error")
1687-
require.Equal(t, "integer divide by zero (1:3)\n | 1 % 0\n | ..^", fileError.Error())
1687+
require.Equal(t, "runtime error: integer divide by zero (1:3)\n | 1 % 0\n | ..^", fileError.Error())
16881688
require.Equal(t, 2, fileError.Column)
16891689
require.Equal(t, 1, fileError.Line)
16901690
}

0 commit comments

Comments
 (0)