From 22c01b2e6de0bce361b2577aa7122d6f93133f16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charles-Edouard=20Br=C3=A9t=C3=A9ch=C3=A9?= Date: Wed, 15 Mar 2023 13:39:38 +0100 Subject: [PATCH 1/6] fix: remove let support for now MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Charles-Edouard Brétéché --- pkg/functions/default.go | 14 +++---- pkg/functions/functions.go | 38 ++++++++--------- pkg/interpreter/interpreter.go | 38 ++++++++--------- pkg/interpreter/scopes.go | 62 +++++++++++++-------------- pkg/interpreter/scopes_test.go | 76 +++++++++++++++++----------------- 5 files changed, 114 insertions(+), 114 deletions(-) diff --git a/pkg/functions/default.go b/pkg/functions/default.go index 66bbf49..b632f8a 100644 --- a/pkg/functions/default.go +++ b/pkg/functions/default.go @@ -101,13 +101,13 @@ func GetDefaultFunctions() []FunctionEntry { {Types: []JpType{JpString}}, }, Handler: jpfLower, - }, { - Name: "let", - Arguments: []ArgSpec{ - {Types: []JpType{JpObject}}, - {Types: []JpType{JpExpref}}, - }, - Handler: jpfLet, + // }, { + // Name: "let", + // Arguments: []ArgSpec{ + // {Types: []JpType{JpObject}}, + // {Types: []JpType{JpExpref}}, + // }, + // Handler: jpfLet, }, { Name: "map", Arguments: []ArgSpec{ diff --git a/pkg/functions/functions.go b/pkg/functions/functions.go index 3337caa..0bdd5a6 100644 --- a/pkg/functions/functions.go +++ b/pkg/functions/functions.go @@ -18,7 +18,7 @@ import ( type ( JpFunction = func([]interface{}) (interface{}, error) - ExpRef = func(interface{}, map[string]interface{}) (interface{}, error) + ExpRef = func(interface{} /*, map[string]interface{}*/) (interface{}, error) JpType string ) @@ -230,7 +230,7 @@ func jpfGroupBy(arguments []interface{}) (interface{}, error) { } groups := map[string]interface{}{} for _, element := range arr { - spec, err := exp(element, nil) + spec, err := exp(element) if err != nil { return nil, err } @@ -294,22 +294,22 @@ func jpfLower(arguments []interface{}) (interface{}, error) { return strings.ToLower(arguments[0].(string)), nil } -func jpfLet(arguments []interface{}) (interface{}, error) { - scope := arguments[0].(map[string]interface{}) - exp := arguments[1].(ExpRef) - result, err := exp(nil, scope) - if err != nil { - return nil, err - } - return result, nil -} +// func jpfLet(arguments []interface{}) (interface{}, error) { +// scope := arguments[0].(map[string]interface{}) +// exp := arguments[1].(ExpRef) +// result, err := exp(nil, scope) +// if err != nil { +// return nil, err +// } +// return result, nil +// } func jpfMap(arguments []interface{}) (interface{}, error) { exp := arguments[0].(ExpRef) arr := arguments[1].([]interface{}) mapped := make([]interface{}, 0, len(arr)) for _, value := range arr { - current, err := exp(value, nil) + current, err := exp(value) if err != nil { return nil, err } @@ -359,7 +359,7 @@ func jpfMaxBy(arguments []interface{}) (interface{}, error) { } else if len(arr) == 1 { return arr[0], nil } - start, err := exp(arr[0], nil) + start, err := exp(arr[0]) if err != nil { return nil, err } @@ -368,7 +368,7 @@ func jpfMaxBy(arguments []interface{}) (interface{}, error) { bestVal := t bestItem := arr[0] for _, item := range arr[1:] { - result, err := exp(item, nil) + result, err := exp(item) if err != nil { return nil, err } @@ -386,7 +386,7 @@ func jpfMaxBy(arguments []interface{}) (interface{}, error) { bestVal := t bestItem := arr[0] for _, item := range arr[1:] { - result, err := exp(item, nil) + result, err := exp(item) if err != nil { return nil, err } @@ -456,7 +456,7 @@ func jpfMinBy(arguments []interface{}) (interface{}, error) { } else if len(arr) == 1 { return arr[0], nil } - start, err := exp(arr[0], nil) + start, err := exp(arr[0]) if err != nil { return nil, err } @@ -464,7 +464,7 @@ func jpfMinBy(arguments []interface{}) (interface{}, error) { bestVal := t bestItem := arr[0] for _, item := range arr[1:] { - result, err := exp(item, nil) + result, err := exp(item) if err != nil { return nil, err } @@ -482,7 +482,7 @@ func jpfMinBy(arguments []interface{}) (interface{}, error) { bestVal := t bestItem := arr[0] for _, item := range arr[1:] { - result, err := exp(item, nil) + result, err := exp(item) if err != nil { return nil, err } @@ -617,7 +617,7 @@ func jpfSortBy(arguments []interface{}) (interface{}, error) { } var sortKeys []interface{} for _, item := range arr { - if value, err := exp(item, nil); err != nil { + if value, err := exp(item); err != nil { return nil, err } else { sortKeys = append(sortKeys, value) diff --git a/pkg/interpreter/interpreter.go b/pkg/interpreter/interpreter.go index 185eff9..0e57136 100644 --- a/pkg/interpreter/interpreter.go +++ b/pkg/interpreter/interpreter.go @@ -18,30 +18,30 @@ This is a tree based interpreter. It walks the AST and directly */ type Interpreter interface { Execute(parsing.ASTNode, interface{}) (interface{}, error) - WithScope(map[string]interface{}) Interpreter + // WithScope(map[string]interface{}) Interpreter } type treeInterpreter struct { caller FunctionCaller - scope Scope - root interface{} + // scope Scope + root interface{} } func NewInterpreter(data interface{}, caller FunctionCaller) Interpreter { return &treeInterpreter{ caller: caller, - scope: newScope(nil), - root: data, + // scope: newScope(nil), + root: data, } } -func (intr *treeInterpreter) WithScope(data map[string]interface{}) Interpreter { - return &treeInterpreter{ - caller: intr.caller, - scope: intr.scope.With(data), - root: intr.root, - } -} +// func (intr *treeInterpreter) WithScope(data map[string]interface{}) Interpreter { +// return &treeInterpreter{ +// caller: intr.caller, +// scope: intr.scope.With(data), +// root: intr.root, +// } +// } // Execute takes an ASTNode and input data and interprets the AST directly. // It will produce the result of applying the JMESPath expression associated @@ -130,10 +130,10 @@ func (intr *treeInterpreter) Execute(node parsing.ASTNode, value interface{}) (i return leftNum <= rightNum, nil } case parsing.ASTExpRef: - return func(data interface{}, scope map[string]interface{}) (interface{}, error) { - if scope != nil { - return intr.WithScope(scope).Execute(node.Children[0], value) - } + return func(data interface{} /*, scope map[string]interface{}*/) (interface{}, error) { + // if scope != nil { + // return intr.WithScope(scope).Execute(node.Children[0], value) + // } return intr.Execute(node.Children[0], data) }, nil case parsing.ASTFunctionExpression: @@ -159,9 +159,9 @@ func (intr *treeInterpreter) Execute(node parsing.ASTNode, value interface{}) (i if result != nil { return result, nil } - if result, ok := intr.scope.GetValue(key); ok { - return result, nil - } + // if result, ok := intr.scope.GetValue(key); ok { + // return result, nil + // } return nil, nil case parsing.ASTFilterProjection: left, err := intr.Execute(node.Children[0], value) diff --git a/pkg/interpreter/scopes.go b/pkg/interpreter/scopes.go index 3331672..56e0702 100644 --- a/pkg/interpreter/scopes.go +++ b/pkg/interpreter/scopes.go @@ -1,37 +1,37 @@ package interpreter -type Scope interface { - GetValue(string) (interface{}, bool) - With(data map[string]interface{}) Scope -} +// type Scope interface { +// GetValue(string) (interface{}, bool) +// With(data map[string]interface{}) Scope +// } -type scope struct { - inner Scope - data map[string]interface{} -} +// type scope struct { +// inner Scope +// data map[string]interface{} +// } -// newScope creates a new instance of JMESPath scope. -func newScope(data map[string]interface{}) Scope { - return scope{ - data: data, - } -} +// // newScope creates a new instance of JMESPath scope. +// func newScope(data map[string]interface{}) Scope { +// return scope{ +// data: data, +// } +// } -func (s scope) GetValue(identifier string) (interface{}, bool) { - if s.data != nil { - if item, ok := s.data[identifier]; ok { - return item, true - } - } - if s.inner != nil { - return s.inner.GetValue(identifier) - } - return nil, false -} +// func (s scope) GetValue(identifier string) (interface{}, bool) { +// if s.data != nil { +// if item, ok := s.data[identifier]; ok { +// return item, true +// } +// } +// if s.inner != nil { +// return s.inner.GetValue(identifier) +// } +// return nil, false +// } -func (s scope) With(data map[string]interface{}) Scope { - return scope{ - data: data, - inner: s, - } -} +// func (s scope) With(data map[string]interface{}) Scope { +// return scope{ +// data: data, +// inner: s, +// } +// } diff --git a/pkg/interpreter/scopes_test.go b/pkg/interpreter/scopes_test.go index fd3664f..3ffc985 100644 --- a/pkg/interpreter/scopes_test.go +++ b/pkg/interpreter/scopes_test.go @@ -1,52 +1,52 @@ package interpreter -import ( - "testing" +// import ( +// "testing" - "github.com/stretchr/testify/assert" -) +// "github.com/stretchr/testify/assert" +// ) -func TestScopesMissing(t *testing.T) { - assert := assert.New(t) - scopes := newScope(nil) +// func TestScopesMissing(t *testing.T) { +// assert := assert.New(t) +// scopes := newScope(nil) - _, found := scopes.GetValue("foo") - assert.False(found) -} +// _, found := scopes.GetValue("foo") +// assert.False(found) +// } -func TestScopesRoot(t *testing.T) { - assert := assert.New(t) - scopes := newScope(map[string]interface{}{"foo": "bar"}) +// func TestScopesRoot(t *testing.T) { +// assert := assert.New(t) +// scopes := newScope(map[string]interface{}{"foo": "bar"}) - value, found := scopes.GetValue("foo") - assert.True(found) - assert.Equal("bar", value.(string)) -} +// value, found := scopes.GetValue("foo") +// assert.True(found) +// assert.Equal("bar", value.(string)) +// } -func TestScopesNested(t *testing.T) { - assert := assert.New(t) - scopes := newScope(nil) +// func TestScopesNested(t *testing.T) { +// assert := assert.New(t) +// scopes := newScope(nil) - { - scopes := scopes.With(map[string]interface{}{"foo": "bar", "qux": "quux"}) +// { +// scopes := scopes.With(map[string]interface{}{"foo": "bar", "qux": "quux"}) - { - scopes := scopes.With(map[string]interface{}{"foo": "baz"}) +// { +// scopes := scopes.With(map[string]interface{}{"foo": "baz"}) - value, found := scopes.GetValue("foo") - assert.True(found) - assert.Equal("baz", value.(string)) +// value, found := scopes.GetValue("foo") +// assert.True(found) +// assert.Equal("baz", value.(string)) - value, found = scopes.GetValue("qux") - assert.True(found) - assert.Equal("quux", value.(string)) - } +// value, found = scopes.GetValue("qux") +// assert.True(found) +// assert.Equal("quux", value.(string)) +// } - value, found := scopes.GetValue("foo") - assert.True(found) - assert.Equal("bar", value.(string)) - } +// value, found := scopes.GetValue("foo") +// assert.True(found) +// assert.Equal("bar", value.(string)) +// } - _, found := scopes.GetValue("foo") - assert.False(found) -} +// _, found := scopes.GetValue("foo") +// assert.False(found) +// } From 69eaaab60d931196266466e1d5f7a322f4549d0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charles-Edouard=20Br=C3=A9t=C3=A9ch=C3=A9?= Date: Wed, 15 Mar 2023 13:43:12 +0100 Subject: [PATCH 2/6] compliance MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Charles-Edouard Brétéché --- jp_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jp_test.go b/jp_test.go index 78c0d18..1218c8d 100644 --- a/jp_test.go +++ b/jp_test.go @@ -38,7 +38,7 @@ var whiteListed = []string{ "compliance/tests/function_strings.json", "compliance/tests/identifiers.json", "compliance/tests/indices.json", - "compliance/tests/lexical_scoping.json", + // "compliance/tests/lexical_scoping.json", "compliance/tests/literal.json", "compliance/tests/multiselect.json", "compliance/tests/ormatch.json", From 737822b6e2fee3fed10d944312fa98574dcdb704 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charles-Edouard=20Br=C3=A9t=C3=A9ch=C3=A9?= Date: Wed, 15 Mar 2023 16:02:21 +0100 Subject: [PATCH 3/6] tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Charles-Edouard Brétéché --- pkg/api/api_test.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pkg/api/api_test.go b/pkg/api/api_test.go index 15d7143..45c6eef 100644 --- a/pkg/api/api_test.go +++ b/pkg/api/api_test.go @@ -64,11 +64,6 @@ func TestSearch(t *testing.T) { expression: "not a valid expression", }, wantErr: true, - }, { - args: args{ - expression: "let({root: @}, &root).root", - data: map[string]interface{}{}, - }, }, { args: args{ expression: "sort_by(@, &@ *`-1.0`)", From 7724bc8179a429e4b871ac6ecc5d0d4c37771885 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charles-Edouard=20Br=C3=A9t=C3=A9ch=C3=A9?= Date: Wed, 15 Mar 2023 16:03:53 +0100 Subject: [PATCH 4/6] tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Charles-Edouard Brétéché --- jp_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jp_test.go b/jp_test.go index 1218c8d..7c95b10 100644 --- a/jp_test.go +++ b/jp_test.go @@ -34,7 +34,7 @@ var whiteListed = []string{ "compliance/tests/filters.json", "compliance/tests/functions.json", "compliance/tests/function_group_by.json", - "compliance/tests/function_let.json", + // "compliance/tests/function_let.json", "compliance/tests/function_strings.json", "compliance/tests/identifiers.json", "compliance/tests/indices.json", From 4e4d0c0f2ea8f85136b9bb87565c74cb81f56194 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charles-Edouard=20Br=C3=A9t=C3=A9ch=C3=A9?= Date: Wed, 15 Mar 2023 16:36:42 +0100 Subject: [PATCH 5/6] clean MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Charles-Edouard Brétéché --- pkg/functions/default.go | 7 ----- pkg/functions/functions.go | 2 +- pkg/interpreter/functions.go | 4 +-- pkg/interpreter/interpreter.go | 25 +++------------- pkg/interpreter/scopes.go | 37 ------------------------ pkg/interpreter/scopes_test.go | 52 ---------------------------------- 6 files changed, 7 insertions(+), 120 deletions(-) delete mode 100644 pkg/interpreter/scopes.go delete mode 100644 pkg/interpreter/scopes_test.go diff --git a/pkg/functions/default.go b/pkg/functions/default.go index b632f8a..8b942db 100644 --- a/pkg/functions/default.go +++ b/pkg/functions/default.go @@ -101,13 +101,6 @@ func GetDefaultFunctions() []FunctionEntry { {Types: []JpType{JpString}}, }, Handler: jpfLower, - // }, { - // Name: "let", - // Arguments: []ArgSpec{ - // {Types: []JpType{JpObject}}, - // {Types: []JpType{JpExpref}}, - // }, - // Handler: jpfLet, }, { Name: "map", Arguments: []ArgSpec{ diff --git a/pkg/functions/functions.go b/pkg/functions/functions.go index 0bdd5a6..d03bf61 100644 --- a/pkg/functions/functions.go +++ b/pkg/functions/functions.go @@ -18,7 +18,7 @@ import ( type ( JpFunction = func([]interface{}) (interface{}, error) - ExpRef = func(interface{} /*, map[string]interface{}*/) (interface{}, error) + ExpRef = func(interface{}) (interface{}, error) JpType string ) diff --git a/pkg/interpreter/functions.go b/pkg/interpreter/functions.go index 59f2d91..6e32ff6 100644 --- a/pkg/interpreter/functions.go +++ b/pkg/interpreter/functions.go @@ -10,7 +10,7 @@ import ( ) type FunctionCaller interface { - CallFunction(string, []interface{}, Interpreter) (interface{}, error) + CallFunction(string, []interface{}) (interface{}, error) } type functionEntry struct { @@ -146,7 +146,7 @@ func typeCheck(a functions.ArgSpec, arg interface{}) error { return fmt.Errorf("invalid type for: %v, expected: %#v", arg, a.Types) } -func (f *functionCaller) CallFunction(name string, arguments []interface{}, intr Interpreter) (interface{}, error) { +func (f *functionCaller) CallFunction(name string, arguments []interface{}) (interface{}, error) { entry, ok := f.functionTable[name] if !ok { return nil, errors.New("unknown function: " + name) diff --git a/pkg/interpreter/interpreter.go b/pkg/interpreter/interpreter.go index 0e57136..5f837a1 100644 --- a/pkg/interpreter/interpreter.go +++ b/pkg/interpreter/interpreter.go @@ -18,31 +18,20 @@ This is a tree based interpreter. It walks the AST and directly */ type Interpreter interface { Execute(parsing.ASTNode, interface{}) (interface{}, error) - // WithScope(map[string]interface{}) Interpreter } type treeInterpreter struct { caller FunctionCaller - // scope Scope - root interface{} + root interface{} } func NewInterpreter(data interface{}, caller FunctionCaller) Interpreter { return &treeInterpreter{ caller: caller, - // scope: newScope(nil), - root: data, + root: data, } } -// func (intr *treeInterpreter) WithScope(data map[string]interface{}) Interpreter { -// return &treeInterpreter{ -// caller: intr.caller, -// scope: intr.scope.With(data), -// root: intr.root, -// } -// } - // Execute takes an ASTNode and input data and interprets the AST directly. // It will produce the result of applying the JMESPath expression associated // with the ASTNode to the input data "value". @@ -130,10 +119,7 @@ func (intr *treeInterpreter) Execute(node parsing.ASTNode, value interface{}) (i return leftNum <= rightNum, nil } case parsing.ASTExpRef: - return func(data interface{} /*, scope map[string]interface{}*/) (interface{}, error) { - // if scope != nil { - // return intr.WithScope(scope).Execute(node.Children[0], value) - // } + return func(data interface{}) (interface{}, error) { return intr.Execute(node.Children[0], data) }, nil case parsing.ASTFunctionExpression: @@ -145,7 +131,7 @@ func (intr *treeInterpreter) Execute(node parsing.ASTNode, value interface{}) (i } resolvedArgs = append(resolvedArgs, current) } - return intr.caller.CallFunction(node.Value.(string), resolvedArgs, intr) + return intr.caller.CallFunction(node.Value.(string), resolvedArgs) case parsing.ASTField: key := node.Value.(string) var result interface{} @@ -159,9 +145,6 @@ func (intr *treeInterpreter) Execute(node parsing.ASTNode, value interface{}) (i if result != nil { return result, nil } - // if result, ok := intr.scope.GetValue(key); ok { - // return result, nil - // } return nil, nil case parsing.ASTFilterProjection: left, err := intr.Execute(node.Children[0], value) diff --git a/pkg/interpreter/scopes.go b/pkg/interpreter/scopes.go deleted file mode 100644 index 56e0702..0000000 --- a/pkg/interpreter/scopes.go +++ /dev/null @@ -1,37 +0,0 @@ -package interpreter - -// type Scope interface { -// GetValue(string) (interface{}, bool) -// With(data map[string]interface{}) Scope -// } - -// type scope struct { -// inner Scope -// data map[string]interface{} -// } - -// // newScope creates a new instance of JMESPath scope. -// func newScope(data map[string]interface{}) Scope { -// return scope{ -// data: data, -// } -// } - -// func (s scope) GetValue(identifier string) (interface{}, bool) { -// if s.data != nil { -// if item, ok := s.data[identifier]; ok { -// return item, true -// } -// } -// if s.inner != nil { -// return s.inner.GetValue(identifier) -// } -// return nil, false -// } - -// func (s scope) With(data map[string]interface{}) Scope { -// return scope{ -// data: data, -// inner: s, -// } -// } diff --git a/pkg/interpreter/scopes_test.go b/pkg/interpreter/scopes_test.go deleted file mode 100644 index 3ffc985..0000000 --- a/pkg/interpreter/scopes_test.go +++ /dev/null @@ -1,52 +0,0 @@ -package interpreter - -// import ( -// "testing" - -// "github.com/stretchr/testify/assert" -// ) - -// func TestScopesMissing(t *testing.T) { -// assert := assert.New(t) -// scopes := newScope(nil) - -// _, found := scopes.GetValue("foo") -// assert.False(found) -// } - -// func TestScopesRoot(t *testing.T) { -// assert := assert.New(t) -// scopes := newScope(map[string]interface{}{"foo": "bar"}) - -// value, found := scopes.GetValue("foo") -// assert.True(found) -// assert.Equal("bar", value.(string)) -// } - -// func TestScopesNested(t *testing.T) { -// assert := assert.New(t) -// scopes := newScope(nil) - -// { -// scopes := scopes.With(map[string]interface{}{"foo": "bar", "qux": "quux"}) - -// { -// scopes := scopes.With(map[string]interface{}{"foo": "baz"}) - -// value, found := scopes.GetValue("foo") -// assert.True(found) -// assert.Equal("baz", value.(string)) - -// value, found = scopes.GetValue("qux") -// assert.True(found) -// assert.Equal("quux", value.(string)) -// } - -// value, found := scopes.GetValue("foo") -// assert.True(found) -// assert.Equal("bar", value.(string)) -// } - -// _, found := scopes.GetValue("foo") -// assert.False(found) -// } From ea2bce58bfa43dc36e1d9787cc124bedb8b9736d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charles-Edouard=20Br=C3=A9t=C3=A9ch=C3=A9?= Date: Wed, 15 Mar 2023 16:37:59 +0100 Subject: [PATCH 6/6] clean MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Charles-Edouard Brétéché --- pkg/functions/functions.go | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/pkg/functions/functions.go b/pkg/functions/functions.go index d03bf61..53b6312 100644 --- a/pkg/functions/functions.go +++ b/pkg/functions/functions.go @@ -294,16 +294,6 @@ func jpfLower(arguments []interface{}) (interface{}, error) { return strings.ToLower(arguments[0].(string)), nil } -// func jpfLet(arguments []interface{}) (interface{}, error) { -// scope := arguments[0].(map[string]interface{}) -// exp := arguments[1].(ExpRef) -// result, err := exp(nil, scope) -// if err != nil { -// return nil, err -// } -// return result, nil -// } - func jpfMap(arguments []interface{}) (interface{}, error) { exp := arguments[0].(ExpRef) arr := arguments[1].([]interface{})