linked-list-iterator and context operator $$ enhancement
This commit is contained in:
@@ -19,6 +19,8 @@ func NewIterator(ctx kern.ExprContext, value any, ops []*scan.Term) (it kern.Ite
|
|||||||
switch v := value.(type) {
|
switch v := value.(type) {
|
||||||
case *kern.ListType:
|
case *kern.ListType:
|
||||||
it = NewListIterator(v, nil)
|
it = NewListIterator(v, nil)
|
||||||
|
case *kern.LinkedList:
|
||||||
|
it = NewLinkedListIterator(v, nil)
|
||||||
case *kern.DictType:
|
case *kern.DictType:
|
||||||
it, err = NewDictIterator(v, nil)
|
it, err = NewDictIterator(v, nil)
|
||||||
case []any:
|
case []any:
|
||||||
|
|||||||
+16
-58
@@ -13,59 +13,23 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type LinkedListIterator struct {
|
type LinkedListIterator struct {
|
||||||
a *kern.ListType
|
a *kern.LinkedList
|
||||||
count int64
|
count int64
|
||||||
index int64
|
index int64
|
||||||
start int64
|
current *kern.ListNode
|
||||||
stop int64
|
|
||||||
step int64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewLinkedListIterator(list *kern.ListType, args []any) (it *LinkedListIterator) {
|
func NewLinkedListIterator(list *kern.LinkedList, args []any) (it *LinkedListIterator) {
|
||||||
var argc int = 0
|
it = &LinkedListIterator{a: list, count: 0, index: -1, current: list.FirstNode()}
|
||||||
listLen := int64(len(([]any)(*list)))
|
|
||||||
if args != nil {
|
|
||||||
argc = len(args)
|
|
||||||
}
|
|
||||||
it = &LinkedListIterator{a: list, count: 0, index: -1, start: 0, stop: listLen - 1, step: 1}
|
|
||||||
if argc >= 1 {
|
|
||||||
if i, err := kern.ToGoInt64(args[0], "start index"); err == nil {
|
|
||||||
if i < 0 {
|
|
||||||
i = listLen + i
|
|
||||||
}
|
|
||||||
it.start = i
|
|
||||||
}
|
|
||||||
if argc >= 2 {
|
|
||||||
if i, err := kern.ToGoInt64(args[1], "stop index"); err == nil {
|
|
||||||
if i < 0 {
|
|
||||||
i = listLen + i
|
|
||||||
}
|
|
||||||
it.stop = i
|
|
||||||
}
|
|
||||||
if argc >= 3 {
|
|
||||||
if i, err := kern.ToGoInt64(args[2], "step"); err == nil {
|
|
||||||
if i < 0 {
|
|
||||||
i = -i
|
|
||||||
}
|
|
||||||
if it.start > it.stop {
|
|
||||||
it.step = -i
|
|
||||||
} else {
|
|
||||||
it.step = i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
it.index = it.start - it.step
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (it *LinkedListIterator) String() string {
|
func (it *LinkedListIterator) String() string {
|
||||||
var l = int64(0)
|
var l = int64(0)
|
||||||
if it.a != nil {
|
if it.a != nil {
|
||||||
l = int64(len(*it.a))
|
l = int64(it.a.Len())
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("$([#%d])", l)
|
return fmt.Sprintf("$([<#%d>])", l)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (it *LinkedListIterator) TypeName() string {
|
func (it *LinkedListIterator) TypeName() string {
|
||||||
@@ -73,7 +37,6 @@ func (it *LinkedListIterator) TypeName() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (it *LinkedListIterator) HasOperation(name string) bool {
|
func (it *LinkedListIterator) HasOperation(name string) bool {
|
||||||
//yes := name == expr.NextName || name == expr.ResetName || name == expr.IndexName || name == expr.CountName || name == expr.CurrentName
|
|
||||||
yes := slices.Contains([]string{kern.NextName, kern.ResetName, kern.IndexName, kern.CountName, kern.CurrentName}, name)
|
yes := slices.Contains([]string{kern.NextName, kern.ResetName, kern.IndexName, kern.CountName, kern.CurrentName}, name)
|
||||||
return yes
|
return yes
|
||||||
}
|
}
|
||||||
@@ -99,28 +62,22 @@ func (it *LinkedListIterator) CallOperation(name string, args map[string]any) (v
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (it *LinkedListIterator) Current() (item any, err error) {
|
func (it *LinkedListIterator) Current() (item any, err error) {
|
||||||
a := *(it.a)
|
if it.current != nil {
|
||||||
if it.start <= it.stop {
|
item = it.current.Data()
|
||||||
if it.stop < int64(len(a)) && it.index >= it.start && it.index <= it.stop {
|
|
||||||
item = a[it.index]
|
|
||||||
} else {
|
} else {
|
||||||
err = io.EOF
|
err = io.EOF
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if it.start < int64(len(a)) && it.index >= it.stop && it.index <= it.start {
|
|
||||||
item = a[it.index]
|
|
||||||
} else {
|
|
||||||
err = io.EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (it *LinkedListIterator) Next() (item any, err error) {
|
func (it *LinkedListIterator) Next() (item any, err error) {
|
||||||
it.index += it.step
|
if it.current != nil {
|
||||||
if item, err = it.Current(); err != io.EOF {
|
item = it.current.Data()
|
||||||
|
it.current = it.current.Next()
|
||||||
|
it.index++
|
||||||
it.count++
|
it.count++
|
||||||
|
} else {
|
||||||
|
err = io.EOF
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -134,7 +91,8 @@ func (it *LinkedListIterator) Count() int64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (it *LinkedListIterator) Reset() error {
|
func (it *LinkedListIterator) Reset() error {
|
||||||
it.index = it.start - it.step
|
it.current = it.a.FirstNode()
|
||||||
|
it.index = -1
|
||||||
it.count = 0
|
it.count = 0
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -137,6 +137,11 @@ func evalIterator(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
|||||||
if args, err = evalSiblings(ctx, opTerm.Children, nil); err == nil {
|
if args, err = evalSiblings(ctx, opTerm.Children, nil); err == nil {
|
||||||
v = NewListIterator(list, args)
|
v = NewListIterator(list, args)
|
||||||
}
|
}
|
||||||
|
} else if list, ok := firstChildValue.(*kern.LinkedList); ok {
|
||||||
|
var args []any
|
||||||
|
if args, err = evalSiblings(ctx, opTerm.Children, nil); err == nil {
|
||||||
|
v = NewLinkedListIterator(list, args)
|
||||||
|
}
|
||||||
} else if intVal, ok := firstChildValue.(int64); ok {
|
} else if intVal, ok := firstChildValue.(int64); ok {
|
||||||
var args []any
|
var args []any
|
||||||
if args, err = evalSiblings(ctx, opTerm.Children, intVal); err == nil {
|
if args, err = evalSiblings(ctx, opTerm.Children, intVal); err == nil {
|
||||||
|
|||||||
+7
-3
@@ -58,7 +58,11 @@ func evalContextValue(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error
|
|||||||
v = d
|
v = d
|
||||||
}
|
}
|
||||||
} else if childValue != nil {
|
} else if childValue != nil {
|
||||||
if it, ok := childValue.(kern.Iterator); ok {
|
it, ok := childValue.(kern.Iterator)
|
||||||
|
if !ok {
|
||||||
|
it, err = NewIterator(ctx, childValue, nil)
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
var item any
|
var item any
|
||||||
// values := kern.NewListA()
|
// values := kern.NewListA()
|
||||||
values := kern.NewLinkedListA()
|
values := kern.NewLinkedListA()
|
||||||
@@ -70,8 +74,8 @@ func evalContextValue(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error
|
|||||||
err = nil
|
err = nil
|
||||||
v = values
|
v = values
|
||||||
}
|
}
|
||||||
} else {
|
// } else {
|
||||||
err = opTerm.ErrIncompatiblePrefixPostfixType(childValue)
|
// err = opTerm.ErrIncompatiblePrefixPostfixType(childValue)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err = opTerm.ErrIncompatiblePrefixPostfixType(childValue)
|
err = opTerm.ErrIncompatiblePrefixPostfixType(childValue)
|
||||||
|
|||||||
+2
-2
@@ -13,8 +13,8 @@ import (
|
|||||||
func TestIterIterator(t *testing.T) {
|
func TestIterIterator(t *testing.T) {
|
||||||
section := "Iter-Iter"
|
section := "Iter-Iter"
|
||||||
inputs := []inputType{
|
inputs := []inputType{
|
||||||
/* 1 */ {`it=$(4); $$($(it) filter ${_}==100)`, kern.NewListA(), nil},
|
/* 1 */ {`it=$(4); $$($(it) filter ${_}==100)`, kern.NewLinkedListA(), nil},
|
||||||
/* 2 */ {`it=$(4); $$($(it, $_) filter ${_}==100)`, kern.NewListA(), nil},
|
/* 2 */ {`it=$(4); $$($(it, $_) filter ${_}==100)`, kern.NewLinkedListA(), nil},
|
||||||
/* 3 */ {`it=$(4); $(it, 10+$_, last-1) digest ${_}`, int64(12), nil},
|
/* 3 */ {`it=$(4); $(it, 10+$_, last-1) digest ${_}`, int64(12), nil},
|
||||||
/* 4 */ {`f=func(n){last-n}; it=$(4); $(it, 10+$_, f(-1)) digest ${_}`, int64(14), nil},
|
/* 4 */ {`f=func(n){last-n}; it=$(4); $(it, 10+$_, f(-1)) digest ${_}`, int64(14), nil},
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-9
@@ -44,8 +44,8 @@ func TestIteratorParser(t *testing.T) {
|
|||||||
func TestFilterIterator(t *testing.T) {
|
func TestFilterIterator(t *testing.T) {
|
||||||
section := "Iterator-Filter"
|
section := "Iterator-Filter"
|
||||||
inputs := []inputType{
|
inputs := []inputType{
|
||||||
/* 1 */ {`$$([1,2,3] filter $_%2==0)`, kern.NewList([]any{int64(2)}), nil},
|
/* 1 */ {`$$([1,2,3] filter $_%2==0)`, kern.NewLinkedListA(2), nil},
|
||||||
/* 2 */ {`it = [1,2,3] filter $_%2!=1; $$(it)`, kern.NewList([]any{int64(2)}), nil},
|
/* 2 */ {`it = [1,2,3] filter $_%2!=1; $$(it)`, kern.NewLinkedListA(2), nil},
|
||||||
/* 3 */ {`builtin "os.file"; #$$(fileLineIterator("test-file.txt") filter (#${_} == 2))`, int64(0), nil},
|
/* 3 */ {`builtin "os.file"; #$$(fileLineIterator("test-file.txt") filter (#${_} == 2))`, int64(0), nil},
|
||||||
/* 4 */ {`builtin "os.file"; #$$(fileLineIterator("test-file.txt") filter (#${_} == 3))`, int64(2), nil},
|
/* 4 */ {`builtin "os.file"; #$$(fileLineIterator("test-file.txt") filter (#${_} == 3))`, int64(2), nil},
|
||||||
}
|
}
|
||||||
@@ -69,11 +69,11 @@ func TestDigestIterator(t *testing.T) {
|
|||||||
func TestCatIterator(t *testing.T) {
|
func TestCatIterator(t *testing.T) {
|
||||||
section := "Iterator-Cat"
|
section := "Iterator-Cat"
|
||||||
inputs := []inputType{
|
inputs := []inputType{
|
||||||
/* 1 */ {`$$([1] cat [])`, kern.NewList([]any{int64(1)}), nil},
|
/* 1 */ {`$$([1] cat [])`, kern.NewLinkedListA(1), nil},
|
||||||
/* 2 */ {`$$([1] cat [2])`, kern.NewList([]any{int64(1), int64(2)}), nil},
|
/* 2 */ {`$$([1] cat [2])`, kern.NewLinkedListA(1, 2), nil},
|
||||||
/* 3 */ {`$$([1] cat nil)`, kern.NewList([]any{int64(1)}), nil},
|
/* 3 */ {`$$([1] cat nil)`, kern.NewLinkedListA(1), nil},
|
||||||
/* 4 */ {`$$(nil cat [2])`, kern.NewList([]any{int64(2)}), nil},
|
/* 4 */ {`$$(nil cat [2])`, kern.NewLinkedListA(2), nil},
|
||||||
/* 5 */ {`$$(nil cat nil)`, kern.NewList([]any{}), nil},
|
/* 5 */ {`$$(nil cat nil)`, kern.NewLinkedListA(), nil},
|
||||||
/* 6 */ {`$$(["a","b"] cat ["x"-true])`, nil, `[1:23] left operand 'x' [string] and right operand 'true' [bool] are not compatible with operator "-"`},
|
/* 6 */ {`$$(["a","b"] cat ["x"-true])`, nil, `[1:23] left operand 'x' [string] and right operand 'true' [bool] are not compatible with operator "-"`},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,10 +84,10 @@ func TestCatIterator(t *testing.T) {
|
|||||||
func TestMapIterator(t *testing.T) {
|
func TestMapIterator(t *testing.T) {
|
||||||
section := "Iterator-Map"
|
section := "Iterator-Map"
|
||||||
inputs := []inputType{
|
inputs := []inputType{
|
||||||
/* 1 */ {`$$([3,4,5] map ${_#})`, kern.NewList([]any{int64(1), int64(2), int64(3)}), nil},
|
/* 1 */ {`$$([3,4,5] map ${_#})`, kern.NewLinkedListA(1, 2, 3), nil},
|
||||||
/* 2 */ {`#$$($(10) map ${_})`, int64(10), nil},
|
/* 2 */ {`#$$($(10) map ${_})`, int64(10), nil},
|
||||||
/* 3 */ {`#$$($(10,0) map ${_})`, int64(10), nil},
|
/* 3 */ {`#$$($(10,0) map ${_})`, int64(10), nil},
|
||||||
/* 4 */ {`builtin "os.file"; $$(fileLineIterator("test-file.txt") map ${__})`, kern.NewList([]any{int64(0), int64(1)}), nil},
|
/* 4 */ {`builtin "os.file"; $$(fileLineIterator("test-file.txt") map ${__})`, kern.NewLinkedListA(0, 1), nil},
|
||||||
/* 5 */ {`$$(["1", "2", "3"] map int())`, nil, `int(): too few params -- expected 1, got 0`},
|
/* 5 */ {`$$(["1", "2", "3"] map int())`, nil, `int(): too few params -- expected 1, got 0`},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -71,10 +71,12 @@ func TestLinkedListParser(t *testing.T) {
|
|||||||
|
|
||||||
inputs := []inputType{
|
inputs := []inputType{
|
||||||
/* 1 */ {`[<1,2>]`, kern.NewLinkedListA(1, 2), nil},
|
/* 1 */ {`[<1,2>]`, kern.NewLinkedListA(1, 2), nil},
|
||||||
|
/* 2 */ {`it=$([<1,2,3>]); it++`, int64(1), nil},
|
||||||
|
/* 3 */ {`it=$([<1,2,3>]); #($$(it))`, int64(3), nil},
|
||||||
}
|
}
|
||||||
|
|
||||||
// t.Setenv("EXPR_PATH", ".")
|
// t.Setenv("EXPR_PATH", ".")
|
||||||
|
|
||||||
// runTestSuiteSpec(t, section, inputs, 44)
|
// runTestSuiteSpec(t, section, inputs, 3)
|
||||||
runTestSuite(t, section, inputs)
|
runTestSuite(t, section, inputs)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user