@@ -17,6 +17,79 @@ import (
17
17
"github.com/expr-lang/expr/parser"
18
18
)
19
19
20
+ func TestOptimize (t * testing.T ) {
21
+ env := map [string ]any {
22
+ "a" : 1 ,
23
+ "b" : 2 ,
24
+ "c" : 3 ,
25
+ }
26
+
27
+ tests := []struct {
28
+ expr string
29
+ want any
30
+ }{
31
+ {`1 + 2` , 3 },
32
+ {`sum([])` , 0 },
33
+ {`sum([a])` , 1 },
34
+ {`sum([a, b])` , 3 },
35
+ {`sum([a, b, c])` , 6 },
36
+ {`sum([a, b, c, 4])` , 10 },
37
+ {`all(1..3, {# > 0}) && all(1..3, {# < 4})` , true },
38
+ {`all(1..3, {# > 2}) && all(1..3, {# < 4})` , false },
39
+ {`all(1..3, {# > 0}) && all(1..3, {# < 2})` , false },
40
+ {`all(1..3, {# > 2}) && all(1..3, {# < 2})` , false },
41
+ {`all(1..3, {# > 0}) || all(1..3, {# < 4})` , true },
42
+ {`all(1..3, {# > 0}) || all(1..3, {# != 2})` , true },
43
+ {`all(1..3, {# != 3}) || all(1..3, {# < 4})` , true },
44
+ {`all(1..3, {# != 3}) || all(1..3, {# != 2})` , false },
45
+ {`none(1..3, {# == 0})` , true },
46
+ {`none(1..3, {# == 0}) && none(1..3, {# == 4})` , true },
47
+ {`none(1..3, {# == 0}) && none(1..3, {# == 3})` , false },
48
+ {`none(1..3, {# == 1}) && none(1..3, {# == 4})` , false },
49
+ {`none(1..3, {# == 1}) && none(1..3, {# == 3})` , false },
50
+ {`none(1..3, {# == 0}) || none(1..3, {# == 4})` , true },
51
+ {`none(1..3, {# == 0}) || none(1..3, {# == 3})` , true },
52
+ {`none(1..3, {# == 1}) || none(1..3, {# == 4})` , true },
53
+ {`none(1..3, {# == 1}) || none(1..3, {# == 3})` , false },
54
+ {`any([1, 1, 0, 1], {# == 0})` , true },
55
+ {`any(1..3, {# == 1}) && any(1..3, {# == 2})` , true },
56
+ {`any(1..3, {# == 0}) && any(1..3, {# == 2})` , false },
57
+ {`any(1..3, {# == 1}) && any(1..3, {# == 4})` , false },
58
+ {`any(1..3, {# == 0}) && any(1..3, {# == 4})` , false },
59
+ {`any(1..3, {# == 1}) || any(1..3, {# == 2})` , true },
60
+ {`any(1..3, {# == 0}) || any(1..3, {# == 2})` , true },
61
+ {`any(1..3, {# == 1}) || any(1..3, {# == 4})` , true },
62
+ {`any(1..3, {# == 0}) || any(1..3, {# == 4})` , false },
63
+ {`one([1, 1, 0, 1], {# == 0}) and not one([1, 0, 0, 1], {# == 0})` , true },
64
+ {`one(1..3, {# == 1}) and one(1..3, {# == 2})` , true },
65
+ {`one(1..3, {# == 1 || # == 2}) and one(1..3, {# == 2})` , false },
66
+ {`one(1..3, {# == 1}) and one(1..3, {# == 2 || # == 3})` , false },
67
+ {`one(1..3, {# == 1 || # == 2}) and one(1..3, {# == 2 || # == 3})` , false },
68
+ {`one(1..3, {# == 1}) or one(1..3, {# == 2})` , true },
69
+ {`one(1..3, {# == 1 || # == 2}) or one(1..3, {# == 2})` , true },
70
+ {`one(1..3, {# == 1}) or one(1..3, {# == 2 || # == 3})` , true },
71
+ {`one(1..3, {# == 1 || # == 2}) or one(1..3, {# == 2 || # == 3})` , false },
72
+ }
73
+
74
+ for _ , tt := range tests {
75
+ t .Run (tt .expr , func (t * testing.T ) {
76
+ program , err := expr .Compile (tt .expr , expr .Env (env ))
77
+ require .NoError (t , err )
78
+
79
+ output , err := expr .Run (program , env )
80
+ require .NoError (t , err )
81
+ assert .Equal (t , tt .want , output )
82
+
83
+ unoptimizedProgram , err := expr .Compile (tt .expr , expr .Env (env ), expr .Optimize (false ))
84
+ require .NoError (t , err )
85
+
86
+ unoptimizedOutput , err := expr .Run (unoptimizedProgram , env )
87
+ require .NoError (t , err )
88
+ assert .Equal (t , tt .want , unoptimizedOutput )
89
+ })
90
+ }
91
+ }
92
+
20
93
func TestOptimize_constant_folding (t * testing.T ) {
21
94
tree , err := parser .Parse (`[1,2,3][5*5-25]` )
22
95
require .NoError (t , err )
0 commit comments