Iterator defined by data-source now only requires one method: next()
This commit is contained in:
parent
6ecbe2feb1
commit
c461fd138e
@ -13,19 +13,29 @@ type dataCursor struct {
|
|||||||
ds map[string]Functor
|
ds map[string]Functor
|
||||||
ctx ExprContext
|
ctx ExprContext
|
||||||
index int
|
index int
|
||||||
|
current any
|
||||||
|
lastErr error
|
||||||
resource any
|
resource any
|
||||||
nextFunc Functor
|
nextFunc Functor
|
||||||
cleanFunc Functor
|
cleanFunc Functor
|
||||||
resetFunc Functor
|
resetFunc Functor
|
||||||
currentFunc Functor
|
// currentFunc Functor
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDataCursor(ctx ExprContext, ds map[string]Functor) (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,
|
||||||
ctx: ctx.Clone(),
|
current: nil,
|
||||||
|
lastErr: nil,
|
||||||
|
resource: resource,
|
||||||
|
ctx: ctx.Clone(),
|
||||||
|
nextFunc: ds[NextName],
|
||||||
|
// currentFunc: ds[CurrentName],
|
||||||
|
cleanFunc: ds[CleanName],
|
||||||
|
resetFunc: ds[ResetName],
|
||||||
}
|
}
|
||||||
|
dc.Next()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,6 +111,7 @@ func (dc *dataCursor) Reset() (success bool, err error) {
|
|||||||
dc.index = -1
|
dc.index = -1
|
||||||
}
|
}
|
||||||
exportObjects(dc.ctx, ctx)
|
exportObjects(dc.ctx, ctx)
|
||||||
|
dc.Next()
|
||||||
} else {
|
} else {
|
||||||
err = errInvalidDataSource()
|
err = errInvalidDataSource()
|
||||||
}
|
}
|
||||||
@ -129,93 +140,71 @@ func (dc *dataCursor) Clean() (success bool, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (dc *dataCursor) Current() (item any, err error) { // must return io.EOF at the last item
|
func (dc *dataCursor) Current() (item any, err error) { // must return io.EOF at the last item
|
||||||
ctx := cloneContext(dc.ctx)
|
if dc.current != nil {
|
||||||
if item, err = dc.currentFunc.Invoke(ctx, CurrentName, []any{}); err == nil && item == nil {
|
item = dc.current
|
||||||
|
} else {
|
||||||
err = io.EOF
|
err = io.EOF
|
||||||
}
|
}
|
||||||
exportObjects(dc.ctx, ctx)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// func (dc *dataCursor) _Next() (item any, err error) { // must return io.EOF after the last item
|
|
||||||
// if dc.resource != nil {
|
|
||||||
// ctx := cloneContext(dc.ctx)
|
|
||||||
// // fmt.Printf("Entering Inner-Ctx [%p]: %s\n", ctx, CtxToString(ctx, 0))
|
|
||||||
// if item, err = dc.nextFunc.Invoke(ctx, nextName, []any{dc.resource}); err == nil {
|
|
||||||
// if item == nil {
|
|
||||||
// err = io.EOF
|
|
||||||
// } else {
|
|
||||||
// dc.index++
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// // fmt.Printf("Exiting Inner-Ctx [%p]: %s\n", ctx, CtxToString(ctx, 0))
|
|
||||||
// exportObjects(dc.ctx, ctx)
|
|
||||||
// // fmt.Printf("Outer-Ctx [%p]: %s\n", dc.ctx, CtxToString(dc.ctx, 0))
|
|
||||||
// } else {
|
|
||||||
// err = errInvalidDataSource()
|
|
||||||
// }
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func (dc *dataCursor) _filter(item any) (filterdItem any, err error) {
|
|
||||||
// if filter, ok := dc.ds[filterName]; ok {
|
|
||||||
// ctx := cloneContext(dc.ctx)
|
|
||||||
// filterdItem, err = filter.Invoke(ctx, filterName, []any{item, dc.index})
|
|
||||||
// } else {
|
|
||||||
// filterdItem = item
|
|
||||||
// }
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
|
|
||||||
func (dc *dataCursor) checkFilter(filter Functor, item any) (accepted bool, err error) {
|
func (dc *dataCursor) checkFilter(filter Functor, item any) (accepted bool, err error) {
|
||||||
var v any
|
var v any
|
||||||
var ok bool
|
var ok bool
|
||||||
ctx := cloneContext(dc.ctx)
|
ctx := cloneContext(dc.ctx)
|
||||||
if v, err = filter.Invoke(ctx, FilterName, []any{item, dc.index}); err == nil && v != nil {
|
if v, err = filter.Invoke(ctx, FilterName, []any{item, dc.index}); err == nil && v != nil {
|
||||||
if accepted, ok = v.(bool); !ok {
|
if accepted, ok = v.(bool); !ok {
|
||||||
accepted = true // NOTE: A non-boolean value that is not nil means the item has been accepted
|
accepted = true // NOTE: A non-boolean value that is not nil means the item has been accepted
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dc *dataCursor) mapItem(mapper Functor, item any) (mappedItem any, err error) {
|
func (dc *dataCursor) mapItem(mapper Functor, item any) (mappedItem any, err error) {
|
||||||
ctx := cloneContext(dc.ctx)
|
ctx := cloneContext(dc.ctx)
|
||||||
mappedItem, err = mapper.Invoke(ctx, MapName, []any{item, dc.index});
|
mappedItem, err = mapper.Invoke(ctx, MapName, []any{item, dc.index})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dc *dataCursor) Next() (item 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
|
var accepted bool
|
||||||
|
if err = dc.lastErr; err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
current = dc.current
|
||||||
if dc.resource != nil {
|
if dc.resource != nil {
|
||||||
filter := dc.ds[FilterName]
|
filter := dc.ds[FilterName]
|
||||||
mapper := dc.ds[MapName]
|
mapper := dc.ds[MapName]
|
||||||
|
var item any
|
||||||
for item == nil && err == nil {
|
for item == nil && dc.lastErr == nil {
|
||||||
ctx := cloneContext(dc.ctx)
|
ctx := cloneContext(dc.ctx)
|
||||||
if item, err = dc.nextFunc.Invoke(ctx, NextName, []any{dc.resource}); err == nil {
|
dc.index++
|
||||||
|
if item, dc.lastErr = dc.nextFunc.Invoke(ctx, NextName, []any{dc.resource, dc.index}); dc.lastErr == nil {
|
||||||
if item == nil {
|
if item == nil {
|
||||||
err = io.EOF
|
dc.lastErr = io.EOF
|
||||||
} else {
|
} else {
|
||||||
dc.index++
|
|
||||||
if filter != nil {
|
if filter != nil {
|
||||||
if accepted, err = dc.checkFilter(filter, item); err != nil || !accepted {
|
if accepted, dc.lastErr = dc.checkFilter(filter, item); dc.lastErr != nil || !accepted {
|
||||||
item = nil
|
item = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if item != nil && mapper != nil {
|
if item != nil && mapper != nil {
|
||||||
item, err = dc.mapItem(mapper, item)
|
item, dc.lastErr = dc.mapItem(mapper, item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exportObjects(dc.ctx, ctx)
|
exportObjects(dc.ctx, ctx)
|
||||||
}
|
}
|
||||||
|
dc.current = item
|
||||||
|
if dc.lastErr != nil {
|
||||||
|
dc.Clean()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
err = errInvalidDataSource()
|
dc.lastErr = errInvalidDataSource()
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dc *dataCursor) Index() int {
|
func (dc *dataCursor) Index() int {
|
||||||
return dc.index
|
return dc.index-1
|
||||||
}
|
}
|
||||||
|
@ -66,8 +66,8 @@ func evalFirstChild(ctx ExprContext, iteratorTerm *term) (value any, err error)
|
|||||||
|
|
||||||
func getDataSourceDict(iteratorTerm *term, firstChildValue any) (ds map[string]Functor, err error) {
|
func getDataSourceDict(iteratorTerm *term, firstChildValue any) (ds map[string]Functor, err error) {
|
||||||
if dictAny, ok := firstChildValue.(*DictType); ok {
|
if dictAny, ok := firstChildValue.(*DictType); ok {
|
||||||
requiredFields := []string{CurrentName, NextName}
|
requiredFields := []string{/*CurrentName,*/ NextName}
|
||||||
fieldsMask := 0b11
|
fieldsMask := 0b1
|
||||||
foundFields := 0
|
foundFields := 0
|
||||||
ds = make(map[string]Functor)
|
ds = make(map[string]Functor)
|
||||||
for keyAny, item := range *dictAny {
|
for keyAny, item := range *dictAny {
|
||||||
@ -108,9 +108,10 @@ func evalIterator(ctx ExprContext, opTerm *term) (v any, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ds != nil {
|
if ds != nil {
|
||||||
dc := NewDataCursor(ctx, ds)
|
var dc *dataCursor
|
||||||
if initFunc, exists := ds[InitName]; exists && initFunc != nil {
|
if initFunc, exists := ds[InitName]; exists && initFunc != nil {
|
||||||
var args []any
|
var args []any
|
||||||
|
var resource any
|
||||||
if len(opTerm.children) > 1 {
|
if len(opTerm.children) > 1 {
|
||||||
if args, err = evalTermArray(ctx, opTerm.children[1:]); err != nil {
|
if args, err = evalTermArray(ctx, opTerm.children[1:]); err != nil {
|
||||||
return
|
return
|
||||||
@ -119,17 +120,20 @@ func evalIterator(ctx ExprContext, opTerm *term) (v any, err error) {
|
|||||||
args = []any{}
|
args = []any{}
|
||||||
}
|
}
|
||||||
|
|
||||||
initCtx := dc.ctx.Clone()
|
initCtx := ctx.Clone()
|
||||||
if dc.resource, err = initFunc.Invoke(initCtx, InitName, args); err != nil {
|
if resource, err = initFunc.Invoke(initCtx, InitName, args); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
exportObjects(dc.ctx, initCtx)
|
dcCtx := ctx.Clone()
|
||||||
|
exportObjects(dcCtx, initCtx)
|
||||||
|
dc = NewDataCursor(dcCtx, ds, resource)
|
||||||
|
//exportObjects(dc.ctx, initCtx)
|
||||||
}
|
}
|
||||||
|
|
||||||
dc.nextFunc = ds[NextName]
|
// dc.nextFunc = ds[NextName]
|
||||||
dc.currentFunc = ds[CurrentName]
|
// dc.currentFunc = ds[CurrentName]
|
||||||
dc.cleanFunc = ds[CleanName]
|
// dc.cleanFunc = ds[CleanName]
|
||||||
dc.resetFunc = ds[ResetName]
|
// dc.resetFunc = ds[ResetName]
|
||||||
|
|
||||||
v = dc
|
v = dc
|
||||||
} else if list, ok := firstChildValue.(*ListType); ok {
|
} else if list, ok := firstChildValue.(*ListType); ok {
|
||||||
|
@ -19,8 +19,8 @@ func TestExpr(t *testing.T) {
|
|||||||
/* 5 */ {`1 ? {1} : [1+0] {3*(1+1)}`, int64(6), nil},
|
/* 5 */ {`1 ? {1} : [1+0] {3*(1+1)}`, int64(6), nil},
|
||||||
/* 6 */ {`
|
/* 6 */ {`
|
||||||
ds={
|
ds={
|
||||||
"init":func(end){@end=end; @current=0 but true},
|
"init":func(@end){@current=0 but true},
|
||||||
"current":func(){current},
|
//"current":func(){current},
|
||||||
"next":func(){
|
"next":func(){
|
||||||
((next=current+1) <= end) ? [true] {@current=next but current} :: {nil}
|
((next=current+1) <= end) ? [true] {@current=next but current} :: {nil}
|
||||||
}
|
}
|
||||||
@ -32,6 +32,6 @@ func TestExpr(t *testing.T) {
|
|||||||
}
|
}
|
||||||
// t.Setenv("EXPR_PATH", ".")
|
// t.Setenv("EXPR_PATH", ".")
|
||||||
|
|
||||||
// parserTestSpec(t, section, inputs, 3)
|
//runTestSuiteSpec(t, section, inputs, 6)
|
||||||
runTestSuite(t, section, inputs)
|
runTestSuite(t, section, inputs)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user