Iterator: new function Count()

This commit is contained in:
Celestino Amoroso 2024-07-21 16:34:52 +02:00
parent c461fd138e
commit d572f3a129
5 changed files with 48 additions and 32 deletions

View File

@ -10,30 +10,30 @@ import (
) )
type dataCursor struct { type dataCursor struct {
ds map[string]Functor ds map[string]Functor
ctx ExprContext ctx ExprContext
index int index int
current any count int
lastErr error current any
resource any lastErr error
nextFunc Functor resource any
cleanFunc Functor nextFunc Functor
resetFunc Functor cleanFunc Functor
// currentFunc Functor resetFunc Functor
} }
func NewDataCursor(ctx ExprContext, ds map[string]Functor, resource any) (dc *dataCursor) { func NewDataCursor(ctx ExprContext, ds map[string]Functor, resource any) (dc *dataCursor) {
dc = &dataCursor{ dc = &dataCursor{
ds: ds, ds: ds,
index: -1, index: -1,
current: nil, count: 0,
lastErr: nil, current: nil,
resource: resource, lastErr: nil,
ctx: ctx.Clone(), resource: resource,
nextFunc: ds[NextName], ctx: ctx.Clone(),
// currentFunc: ds[CurrentName], nextFunc: ds[NextName],
cleanFunc: ds[CleanName], cleanFunc: ds[CleanName],
resetFunc: ds[ResetName], resetFunc: ds[ResetName],
} }
dc.Next() dc.Next()
return return
@ -109,6 +109,7 @@ func (dc *dataCursor) Reset() (success bool, err error) {
ctx := cloneContext(dc.ctx) ctx := cloneContext(dc.ctx)
if _, err = dc.resetFunc.Invoke(ctx, ResetName, []any{dc.resource}); err == nil { if _, err = dc.resetFunc.Invoke(ctx, ResetName, []any{dc.resource}); err == nil {
dc.index = -1 dc.index = -1
dc.count = 0
} }
exportObjects(dc.ctx, ctx) exportObjects(dc.ctx, ctx)
dc.Next() dc.Next()
@ -167,7 +168,6 @@ func (dc *dataCursor) mapItem(mapper Functor, item any) (mappedItem any, err err
} }
func (dc *dataCursor) Next() (current any, err error) { // must return io.EOF after the last item func (dc *dataCursor) Next() (current any, err error) { // must return io.EOF after the last item
var accepted bool
if err = dc.lastErr; err != nil { if err = dc.lastErr; err != nil {
return return
} }
@ -179,15 +179,19 @@ func (dc *dataCursor) Next() (current any, err error) { // must return io.EOF af
for item == nil && dc.lastErr == nil { for item == nil && dc.lastErr == nil {
ctx := cloneContext(dc.ctx) ctx := cloneContext(dc.ctx)
dc.index++ dc.index++
if item, dc.lastErr = dc.nextFunc.Invoke(ctx, NextName, []any{dc.resource, dc.index}); dc.lastErr == nil { if item, dc.lastErr = dc.nextFunc.Invoke(ctx, NextName, []any{dc.resource, dc.index}); dc.lastErr == nil {
if item == nil { if item == nil {
dc.lastErr = io.EOF dc.lastErr = io.EOF
} else { } else {
accepted := true
if filter != nil { if filter != nil {
if accepted, dc.lastErr = dc.checkFilter(filter, item); dc.lastErr != nil || !accepted { if accepted, dc.lastErr = dc.checkFilter(filter, item); dc.lastErr != nil || !accepted {
item = nil item = nil
} }
} }
if accepted {
dc.count++
}
if item != nil && mapper != nil { if item != nil && mapper != nil {
item, dc.lastErr = dc.mapItem(mapper, item) item, dc.lastErr = dc.mapItem(mapper, item)
} }
@ -197,6 +201,7 @@ func (dc *dataCursor) Next() (current any, err error) { // must return io.EOF af
} }
dc.current = item dc.current = item
if dc.lastErr != nil { if dc.lastErr != nil {
dc.index--
dc.Clean() dc.Clean()
} }
} else { } else {
@ -206,5 +211,10 @@ func (dc *dataCursor) Next() (current any, err error) { // must return io.EOF af
} }
func (dc *dataCursor) Index() int { func (dc *dataCursor) Index() int {
return dc.index-1 return dc.index - 1
}
func (dc *dataCursor) Count() int {
return dc.count
} }

View File

@ -28,6 +28,7 @@ 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)
Index() int Index() int
Count() int
} }
type ExtIterator interface { type ExtIterator interface {

View File

@ -143,7 +143,12 @@ func (it *ListIterator) Index() int {
return it.index return it.index
} }
func (it *ListIterator) Count() int {
return it.count
}
func (it *ListIterator) Reset() (bool, error) { func (it *ListIterator) Reset() (bool, error) {
it.index = it.start - it.step it.index = it.start - it.step
it.count = 0
return true, nil return true, nil
} }

View File

@ -30,16 +30,16 @@ func evalLength(ctx ExprContext, opTerm *term) (v any, err error) {
s, _ := childValue.(string) s, _ := childValue.(string)
v = int64(len(s)) v = int64(len(s))
} else if IsDict(childValue) { } else if IsDict(childValue) {
// m, _ := childValue.(map[any]any)
m, _ := childValue.(*DictType) m, _ := childValue.(*DictType)
v = int64(len(*m)) v = int64(len(*m))
} else if it, ok := childValue.(Iterator); ok { } else if it, ok := childValue.(Iterator); ok {
if extIt, ok := childValue.(ExtIterator); ok && extIt.HasOperation(CountName) { v = int64(it.Count())
count, _ := extIt.CallOperation(CountName, nil) // if extIt, ok := childValue.(ExtIterator); ok && extIt.HasOperation(CountName) {
v, _ = ToGoInt(count, "") // count, _ := extIt.CallOperation(CountName, nil)
} else { // v, _ = ToGoInt(count, "")
v = int64(it.Index() + 1) // } else {
} // v = int64(it.Index() + 1)
// }
} else { } else {
err = opTerm.errIncompatibleType(childValue) err = opTerm.errIncompatibleType(childValue)
} }

View File

@ -11,7 +11,7 @@ func TestIteratorParser(t *testing.T) {
inputs := []inputType{ inputs := []inputType{
/* 1 */ {`include "test-resources/iterator.expr"; it=$(ds,3); ^it`, int64(0), nil}, /* 1 */ {`include "test-resources/iterator.expr"; it=$(ds,3); ^it`, int64(0), nil},
/* 2 */ {`include "test-resources/iterator.expr"; it=$(ds,3); it++; it++`, int64(1), nil}, /* 2 */ {`include "test-resources/iterator.expr"; it=$(ds,3); it++; it++`, int64(1), nil},
/* 3 */ {`include "test-resources/iterator.expr"; it=$(ds,3); it++; it++; #it`, int64(2), nil}, /* 3 */ {`include "test-resources/iterator.expr"; it=$(ds,3); it++; it++; #it`, int64(3), nil},
/* 4 */ {`include "test-resources/iterator.expr"; it=$(ds,3); it++; it++; it.reset; ^it`, int64(0), nil}, /* 4 */ {`include "test-resources/iterator.expr"; it=$(ds,3); it++; it++; it.reset; ^it`, int64(0), nil},
/* 5 */ {`builtin "math.arith"; include "test-resources/iterator.expr"; it=$(ds,3); add(it)`, int64(6), nil}, /* 5 */ {`builtin "math.arith"; include "test-resources/iterator.expr"; it=$(ds,3); add(it)`, int64(6), nil},
/* 6 */ {`builtin "math.arith"; include "test-resources/iterator.expr"; it=$(ds,3); mul(it)`, int64(0), nil}, /* 6 */ {`builtin "math.arith"; include "test-resources/iterator.expr"; it=$(ds,3); mul(it)`, int64(0), nil},
@ -27,6 +27,6 @@ func TestIteratorParser(t *testing.T) {
/* 16 */ {`include "test-resources/filter.expr"; it=$(ds,10); it++`, int64(2), nil}, /* 16 */ {`include "test-resources/filter.expr"; it=$(ds,10); it++`, int64(2), nil},
} }
//runTestSuiteSpec(t, section, inputs, 4) //runTestSuiteSpec(t, section, inputs, 3)
runTestSuite(t, section, inputs) runTestSuite(t, section, inputs)
} }