Skip to content

Commit 5133c0f

Browse files
committed
refactor: have script tokens compile expression
update expression, script, and filter tokens to compile expression when created and not runtime
1 parent 325ad13 commit 5133c0f

10 files changed

+291
-205
lines changed

token/expression.go

+14-9
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,23 @@ import (
77
"github.com/evilmonkeyinc/jsonpath/script"
88
)
99

10-
func newExpressionToken(expression string, engine script.Engine, options *option.QueryOptions) *expressionToken {
11-
return &expressionToken{
12-
expression: expression,
13-
engine: engine,
14-
options: options,
10+
func newExpressionToken(expression string, engine script.Engine, options *option.QueryOptions) (*expressionToken, error) {
11+
compiledExpression, err := engine.Compile(expression, options)
12+
if err != nil {
13+
return nil, err
1514
}
15+
16+
return &expressionToken{
17+
expression: expression,
18+
compiledExpression: compiledExpression,
19+
options: options,
20+
}, nil
1621
}
1722

1823
type expressionToken struct {
19-
expression string
20-
engine script.Engine
21-
options *option.QueryOptions
24+
expression string
25+
compiledExpression script.CompiledExpression
26+
options *option.QueryOptions
2227
}
2328

2429
func (token *expressionToken) String() string {
@@ -34,7 +39,7 @@ func (token *expressionToken) Apply(root, current interface{}, next []Token) (in
3439
return nil, getInvalidExpressionEmptyError()
3540
}
3641

37-
value, err := token.engine.Evaluate(root, current, token.expression, token.options)
42+
value, err := token.compiledExpression.Evaluate(root, current)
3843
if err != nil {
3944
return nil, getInvalidExpressionError(err)
4045
}

token/expression_test.go

+16-7
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,16 @@ func (engine *testCompiledExpression) Evaluate(root, current interface{}) (inter
3636
var _ Token = &expressionToken{}
3737

3838
func Test_newExpressionToken(t *testing.T) {
39-
assert.IsType(t, &expressionToken{}, newExpressionToken("", nil, nil))
39+
t.Run("success", func(t *testing.T) {
40+
actual, err := newExpressionToken("", &testEngine{}, nil)
41+
assert.Nil(t, err)
42+
assert.IsType(t, &expressionToken{}, actual)
43+
})
44+
t.Run("fail", func(t *testing.T) {
45+
actual, err := newExpressionToken("", &testEngine{err: fmt.Errorf("fail")}, nil)
46+
assert.EqualError(t, err, "fail")
47+
assert.Nil(t, actual)
48+
})
4049
}
4150

4251
func Test_ExpressionToken_String(t *testing.T) {
@@ -75,8 +84,8 @@ func Test_ExpressionToken_Apply(t *testing.T) {
7584
},
7685
{
7786
token: &expressionToken{
78-
expression: "any",
79-
engine: &testEngine{err: fmt.Errorf("engine error")},
87+
expression: "any",
88+
compiledExpression: &testCompiledExpression{err: fmt.Errorf("engine error")},
8089
},
8190
input: input{},
8291
expected: expected{
@@ -85,8 +94,8 @@ func Test_ExpressionToken_Apply(t *testing.T) {
8594
},
8695
{
8796
token: &expressionToken{
88-
expression: "any",
89-
engine: &testEngine{response: true},
97+
expression: "any",
98+
compiledExpression: &testCompiledExpression{response: true},
9099
},
91100
input: input{},
92101
expected: expected{
@@ -95,8 +104,8 @@ func Test_ExpressionToken_Apply(t *testing.T) {
95104
},
96105
{
97106
token: &expressionToken{
98-
expression: "any",
99-
engine: &testEngine{response: false},
107+
expression: "any",
108+
compiledExpression: &testCompiledExpression{response: false},
100109
},
101110
input: input{
102111
tokens: []Token{&currentToken{}},

token/filter.go

+15-12
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,22 @@ import (
99
"github.com/evilmonkeyinc/jsonpath/script"
1010
)
1111

12-
func newFilterToken(expression string, engine script.Engine, options *option.QueryOptions) *filterToken {
13-
return &filterToken{expression: expression, engine: engine, options: options}
12+
func newFilterToken(expression string, engine script.Engine, options *option.QueryOptions) (*filterToken, error) {
13+
compiledExpression, err := engine.Compile(expression, options)
14+
if err != nil {
15+
return nil, err
16+
}
17+
return &filterToken{
18+
expression: expression,
19+
compiledExpression: compiledExpression,
20+
options: options,
21+
}, nil
1422
}
1523

1624
type filterToken struct {
17-
expression string
18-
engine script.Engine
19-
options *option.QueryOptions
25+
expression string
26+
compiledExpression script.CompiledExpression
27+
options *option.QueryOptions
2028
}
2129

2230
func (token *filterToken) String() string {
@@ -69,11 +77,6 @@ func (token *filterToken) Apply(root, current interface{}, next []Token) (interf
6977
return nil, getInvalidTokenTargetNilError(token.Type(), reflect.Array, reflect.Map, reflect.Slice)
7078
}
7179

72-
compiledExpression, err := token.engine.Compile(token.expression, token.options)
73-
if err != nil {
74-
return nil, getInvalidExpressionError(err)
75-
}
76-
7780
switch objType.Kind() {
7881
case reflect.Map:
7982
keys := objVal.MapKeys()
@@ -82,7 +85,7 @@ func (token *filterToken) Apply(root, current interface{}, next []Token) (interf
8285
for _, kv := range keys {
8386
element := objVal.MapIndex(kv).Interface()
8487

85-
evaluation, err := compiledExpression.Evaluate(root, element)
88+
evaluation, err := token.compiledExpression.Evaluate(root, element)
8689
if err != nil {
8790
// we ignore errors, it has failed evaluation
8891
evaluation = nil
@@ -98,7 +101,7 @@ func (token *filterToken) Apply(root, current interface{}, next []Token) (interf
98101
for i := 0; i < length; i++ {
99102
element := objVal.Index(i).Interface()
100103

101-
evaluation, err := compiledExpression.Evaluate(root, element)
104+
evaluation, err := token.compiledExpression.Evaluate(root, element)
102105
if err != nil {
103106
// we ignore errors, it has failed evaluation
104107
evaluation = nil

0 commit comments

Comments
 (0)