list iterators now support start, stop e step
This commit is contained in:
parent
d9fbe6f36d
commit
2c5f02cc69
@ -9,15 +9,6 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
initName = "init"
|
|
||||||
cleanName = "clean"
|
|
||||||
resetName = "reset"
|
|
||||||
nextName = "next"
|
|
||||||
currentName = "current"
|
|
||||||
indexName = "index"
|
|
||||||
)
|
|
||||||
|
|
||||||
type dataCursor struct {
|
type dataCursor struct {
|
||||||
ds map[string]Functor
|
ds map[string]Functor
|
||||||
ctx ExprContext
|
ctx ExprContext
|
||||||
@ -77,7 +68,7 @@ func (dc *dataCursor) HasOperation(name string) (exists bool) {
|
|||||||
|
|
||||||
func (dc *dataCursor) CallOperation(name string, args []any) (value any, err error) {
|
func (dc *dataCursor) CallOperation(name string, args []any) (value any, err error) {
|
||||||
if name == indexName {
|
if name == indexName {
|
||||||
value = dc.Index()
|
value = int64(dc.Index())
|
||||||
} else if functor, ok := dc.ds[name]; ok && isFunctor(functor) {
|
} else if functor, ok := dc.ds[name]; ok && isFunctor(functor) {
|
||||||
if functor == dc.cleanFunc {
|
if functor == dc.cleanFunc {
|
||||||
value, err = dc.Clean()
|
value, err = dc.Clean()
|
||||||
|
@ -38,7 +38,7 @@ func doAdd(ctx ExprContext, name string, it Iterator) (result any, err error) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
if list, ok := v.(*ListType); ok {
|
if list, ok := v.(*ListType); ok {
|
||||||
if v, err = doAdd(ctx, name, NewListIterator(list)); err != nil {
|
if v, err = doAdd(ctx, name, NewListIterator(list, nil)); err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -114,7 +114,7 @@ func doMul(ctx ExprContext, name string, it Iterator) (result any, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if list, ok := v.(*ListType); ok {
|
if list, ok := v.(*ListType); ok {
|
||||||
if v, err = doMul(ctx, name, NewListIterator(list)); err != nil {
|
if v, err = doMul(ctx, name, NewListIterator(list, nil)); err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ func joinStrFunc(ctx ExprContext, name string, args []any) (result any, err erro
|
|||||||
result = ""
|
result = ""
|
||||||
} else if len(args) == 2 {
|
} else if len(args) == 2 {
|
||||||
if ls, ok := args[1].(*ListType); ok {
|
if ls, ok := args[1].(*ListType); ok {
|
||||||
result, err = doJoinStr(name, sep, NewListIterator(ls))
|
result, err = doJoinStr(name, sep, NewListIterator(ls, nil))
|
||||||
} else if it, ok := args[1].(Iterator); ok {
|
} else if it, ok := args[1].(Iterator); ok {
|
||||||
result, err = doJoinStr(name, sep, it)
|
result, err = doJoinStr(name, sep, it)
|
||||||
} else {
|
} else {
|
||||||
|
65
iter-list.go
65
iter-list.go
@ -11,22 +11,62 @@ import (
|
|||||||
|
|
||||||
type ListIterator struct {
|
type ListIterator struct {
|
||||||
a *ListType
|
a *ListType
|
||||||
|
count int
|
||||||
index int
|
index int
|
||||||
|
start int
|
||||||
|
stop int
|
||||||
|
step int
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewListIterator(list *ListType) *ListIterator {
|
func NewListIterator(list *ListType, args []any) (it *ListIterator) {
|
||||||
return &ListIterator{a: list, index: 0}
|
var argc int = 0
|
||||||
|
listLen := len(([]any)(*list))
|
||||||
|
if args != nil {
|
||||||
|
argc = len(args)
|
||||||
|
}
|
||||||
|
it = &ListIterator{a: list, count: 0, index: -1, start: 0, stop: listLen - 1, step: 1}
|
||||||
|
if argc >= 1 {
|
||||||
|
if i, err := toInt(args[0], "start index"); err == nil {
|
||||||
|
if i < 0 {
|
||||||
|
i = listLen + i
|
||||||
|
}
|
||||||
|
it.start = i
|
||||||
|
}
|
||||||
|
if argc >= 2 {
|
||||||
|
if i, err := toInt(args[1], "stop index"); err == nil {
|
||||||
|
if i < 0 {
|
||||||
|
i = listLen + i
|
||||||
|
}
|
||||||
|
it.stop = i
|
||||||
|
}
|
||||||
|
if argc >= 3 {
|
||||||
|
if i, err := toInt(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
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewArrayIterator(array []any) *ListIterator {
|
func NewArrayIterator(array []any) (it *ListIterator) {
|
||||||
return &ListIterator{a: (*ListType)(&array), index: 0}
|
it = &ListIterator{a: (*ListType)(&array), count: 0, index: -1, start: 0, stop: len(array) - 1, step: 1}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAnyIterator(value any) (it *ListIterator) {
|
func NewAnyIterator(value any) (it *ListIterator) {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
it = NewArrayIterator([]any{})
|
it = NewArrayIterator([]any{})
|
||||||
} else if list, ok := value.(*ListType); ok {
|
} else if list, ok := value.(*ListType); ok {
|
||||||
it = NewListIterator(list)
|
it = NewListIterator(list, nil)
|
||||||
} else if array, ok := value.([]any); ok {
|
} else if array, ok := value.([]any); ok {
|
||||||
it = NewArrayIterator(array)
|
it = NewArrayIterator(array)
|
||||||
} else if it1, ok := value.(*ListIterator); ok {
|
} else if it1, ok := value.(*ListIterator); ok {
|
||||||
@ -46,7 +86,7 @@ func (it *ListIterator) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (it *ListIterator) HasOperation(name string) bool {
|
func (it *ListIterator) HasOperation(name string) bool {
|
||||||
yes := name == resetName || name == indexName
|
yes := name == resetName || name == indexName || name == countName
|
||||||
return yes
|
return yes
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,7 +95,9 @@ func (it *ListIterator) CallOperation(name string, args []any) (v any, err error
|
|||||||
case resetName:
|
case resetName:
|
||||||
v, err = it.Reset()
|
v, err = it.Reset()
|
||||||
case indexName:
|
case indexName:
|
||||||
v = it.Index()
|
v = int64(it.Index())
|
||||||
|
case countName:
|
||||||
|
v = it.count
|
||||||
default:
|
default:
|
||||||
err = errNoOperation(name)
|
err = errNoOperation(name)
|
||||||
}
|
}
|
||||||
@ -64,7 +106,7 @@ func (it *ListIterator) CallOperation(name string, args []any) (v any, err error
|
|||||||
|
|
||||||
func (it *ListIterator) Current() (item any, err error) {
|
func (it *ListIterator) Current() (item any, err error) {
|
||||||
a := *(it.a)
|
a := *(it.a)
|
||||||
if it.index >= 0 && it.index < len(a) {
|
if it.index >= 0 && it.index <= it.stop {
|
||||||
item = a[it.index]
|
item = a[it.index]
|
||||||
} else {
|
} else {
|
||||||
err = io.EOF
|
err = io.EOF
|
||||||
@ -73,17 +115,18 @@ func (it *ListIterator) Current() (item any, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (it *ListIterator) Next() (item any, err error) {
|
func (it *ListIterator) Next() (item any, err error) {
|
||||||
|
it.index += it.step
|
||||||
if item, err = it.Current(); err != io.EOF {
|
if item, err = it.Current(); err != io.EOF {
|
||||||
it.index++
|
it.count++
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (it *ListIterator) Index() int {
|
func (it *ListIterator) Index() int {
|
||||||
return it.index - 1
|
return it.index
|
||||||
}
|
}
|
||||||
|
|
||||||
func (it *ListIterator) Reset() (bool, error) {
|
func (it *ListIterator) Reset() (bool, error) {
|
||||||
it.index = 0
|
it.index = it.start
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
12
iterator.go
12
iterator.go
@ -9,6 +9,18 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Operator names
|
||||||
|
|
||||||
|
const (
|
||||||
|
initName = "init"
|
||||||
|
cleanName = "clean"
|
||||||
|
resetName = "reset"
|
||||||
|
nextName = "next"
|
||||||
|
currentName = "current"
|
||||||
|
indexName = "index"
|
||||||
|
countName = "count"
|
||||||
|
)
|
||||||
|
|
||||||
type Iterator interface {
|
type Iterator interface {
|
||||||
Next() (item any, err error) // must return io.EOF after the last item
|
Next() (item any, err error) // must return io.EOF after the last item
|
||||||
Current() (item any, err error)
|
Current() (item any, err error)
|
||||||
|
@ -133,29 +133,52 @@ func evalIterator(ctx ExprContext, self *term) (v any, err error) {
|
|||||||
|
|
||||||
v = dc
|
v = dc
|
||||||
} else if list, ok := firstChildValue.(*ListType); ok {
|
} else if list, ok := firstChildValue.(*ListType); ok {
|
||||||
v = NewListIterator(list)
|
var args []any
|
||||||
|
if args, err = evalSibling(ctx, self.children, nil); err == nil {
|
||||||
|
v = NewListIterator(list, args)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
var list *ListType
|
var list []any
|
||||||
if list, err = evalChildren(ctx, self.children, firstChildValue); err == nil {
|
if list, err = evalSibling(ctx, self.children, firstChildValue); err == nil {
|
||||||
v = NewListIterator(list)
|
v = NewArrayIterator(list)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func evalChildren(ctx ExprContext, terms []*term, firstChildValue any) (list *ListType, err error) {
|
// func evalChildren(ctx ExprContext, terms []*term, firstChildValue any) (list *ListType, err error) {
|
||||||
items := make(ListType, len(terms))
|
// items := make(ListType, len(terms))
|
||||||
|
// for i, tree := range terms {
|
||||||
|
// var param any
|
||||||
|
// if i == 0 && firstChildValue != nil {
|
||||||
|
// param = firstChildValue
|
||||||
|
// } else if param, err = tree.compute(ctx); err != nil {
|
||||||
|
// break
|
||||||
|
// }
|
||||||
|
// items[i] = param
|
||||||
|
// }
|
||||||
|
// if err == nil {
|
||||||
|
// list = &items
|
||||||
|
// }
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
|
||||||
|
func evalSibling(ctx ExprContext, terms []*term, firstChildValue any) (list []any, err error) {
|
||||||
|
items := make([]any, 0, len(terms))
|
||||||
for i, tree := range terms {
|
for i, tree := range terms {
|
||||||
var param any
|
var param any
|
||||||
if i == 0 && firstChildValue != nil {
|
if i == 0 {
|
||||||
|
if firstChildValue == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
param = firstChildValue
|
param = firstChildValue
|
||||||
} else if param, err = tree.compute(ctx); err != nil {
|
} else if param, err = tree.compute(ctx); err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
items[i] = param
|
items = append(items, param)
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
list = &items
|
list = items
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ func evalBuiltin(ctx ExprContext, self *term) (v any, err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
v = count
|
v = int64(count)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,12 @@ func evalLength(ctx ExprContext, self *term) (v any, err error) {
|
|||||||
s, _ := childValue.(string)
|
s, _ := childValue.(string)
|
||||||
v = int64(len(s))
|
v = int64(len(s))
|
||||||
} else if it, ok := childValue.(Iterator); ok {
|
} else if it, ok := childValue.(Iterator); ok {
|
||||||
v = int64(it.Index() + 1)
|
if extIt, ok := childValue.(ExtIterator); ok && extIt.HasOperation(countName) {
|
||||||
|
count, _ := extIt.CallOperation(countName, nil)
|
||||||
|
v, _ = toInt(count, "")
|
||||||
|
} else {
|
||||||
|
v = int64(it.Index() + 1)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
err = self.errIncompatibleType(childValue)
|
err = self.errIncompatibleType(childValue)
|
||||||
}
|
}
|
||||||
|
@ -174,11 +174,15 @@ func TestParser(t *testing.T) {
|
|||||||
/* 152 */ {`builtin "math.arith"; mul(1|2, 1.0, 2)`, float64(1.0), nil},
|
/* 152 */ {`builtin "math.arith"; mul(1|2, 1.0, 2)`, float64(1.0), nil},
|
||||||
/* 153 */ {`include "iterator.expr"; it=$(ds,3); ()it`, int64(0), nil},
|
/* 153 */ {`include "iterator.expr"; it=$(ds,3); ()it`, int64(0), nil},
|
||||||
/* 154 */ {`include "iterator.expr"; it=$(ds,3); it++; it++`, int64(1), nil},
|
/* 154 */ {`include "iterator.expr"; it=$(ds,3); it++; it++`, int64(1), nil},
|
||||||
/* 155 */ {`include "iterator.expr"; it=$(ds,3); it++; it++; #it`, int64(1), nil},
|
/* 155 */ {`include "iterator.expr"; it=$(ds,3); it++; it++; #it`, int64(2), nil},
|
||||||
/* 156 */ {`include "iterator.expr"; it=$(ds,3); it++; it++; it.reset; ()it`, int64(0), nil},
|
/* 156 */ {`include "iterator.expr"; it=$(ds,3); it++; it++; it.reset; ()it`, int64(0), nil},
|
||||||
/* 157 */ {`builtin "math.arith"; include "iterator.expr"; it=$(ds,3); add(it)`, int64(6), nil},
|
/* 157 */ {`builtin "math.arith"; include "iterator.expr"; it=$(ds,3); add(it)`, int64(6), nil},
|
||||||
/* 158 */ {`builtin "math.arith"; include "iterator.expr"; it=$(ds,3); mul(it)`, int64(0), nil},
|
/* 158 */ {`builtin "math.arith"; include "iterator.expr"; it=$(ds,3); mul(it)`, int64(0), nil},
|
||||||
/* 159 */ {`include "file-reader.expr"; it=$(ds,"int.list"); mul(it)`, int64(12000), nil},
|
/* 159 */ {`include "file-reader.expr"; it=$(ds,"int.list"); mul(it)`, int64(12000), nil},
|
||||||
|
/* 160 */ {`include "file-reader.expr"; it=$(ds,"int.list"); it++; it.index`, int64(0), nil},
|
||||||
|
/* 161 */ {`include "file-reader.expr"; it=$(ds,"int.list"); it.clean`, true, nil},
|
||||||
|
/* 162 */ {`builtin "os.file"`, int64(1), nil},
|
||||||
|
/* 163 */ {`it=$(1,2,3); it++`, int64(1), nil},
|
||||||
}
|
}
|
||||||
check_env_expr_path := 113
|
check_env_expr_path := 113
|
||||||
|
|
||||||
@ -186,7 +190,7 @@ func TestParser(t *testing.T) {
|
|||||||
failed := 0
|
failed := 0
|
||||||
|
|
||||||
// inputs1 := []inputType{
|
// inputs1 := []inputType{
|
||||||
// /* 140 */ {`ds={}; $(ds)`, nil, nil},
|
// /* 159 */ {`include "file-reader.expr"; it=$(ds,"int.list"); mul(it)`, int64(12000), nil},
|
||||||
// }
|
// }
|
||||||
|
|
||||||
for i, input := range inputs {
|
for i, input := range inputs {
|
||||||
|
Loading…
Reference in New Issue
Block a user