Compare commits
No commits in common. "d215d837f6afc611cb96244c0b4e2b702e9205a4" and "dceb31f5426cabe66c4d419e25aad18c1dff975b" have entirely different histories.
d215d837f6
...
dceb31f542
@ -6,7 +6,6 @@ package expr
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
TypeAny = "any"
|
TypeAny = "any"
|
||||||
TypeNil = "nil"
|
|
||||||
TypeBoolean = "boolean"
|
TypeBoolean = "boolean"
|
||||||
TypeFloat = "float"
|
TypeFloat = "float"
|
||||||
TypeFraction = "fraction"
|
TypeFraction = "fraction"
|
||||||
@ -16,7 +15,6 @@ const (
|
|||||||
TypeNumber = "number"
|
TypeNumber = "number"
|
||||||
TypePair = "pair"
|
TypePair = "pair"
|
||||||
TypeString = "string"
|
TypeString = "string"
|
||||||
TypeDict = "dict"
|
|
||||||
TypeListOf = "list-of-"
|
TypeListOf = "list-of-"
|
||||||
TypeListOfStrings = "list-of-strings"
|
TypeListOfStrings = "list-of-strings"
|
||||||
)
|
)
|
||||||
|
213
data-cursor.go
213
data-cursor.go
@ -6,14 +6,12 @@ package expr
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
"slices"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type dataCursor struct {
|
type dataCursor struct {
|
||||||
ds map[string]Functor
|
ds map[string]Functor
|
||||||
ctx ExprContext
|
ctx ExprContext
|
||||||
initState bool // true if no item has produced yet (this replace di initial Next() call in the contructor)
|
initState bool // true if no item has prodiced yet (this replace di initial Next() call in the contructor)
|
||||||
// cursorValid bool // true if resource is nil or if clean has not yet been called
|
|
||||||
index int
|
index int
|
||||||
count int
|
count int
|
||||||
current any
|
current any
|
||||||
@ -28,7 +26,6 @@ func NewDataCursor(ctx ExprContext, ds map[string]Functor, resource any) (dc *da
|
|||||||
dc = &dataCursor{
|
dc = &dataCursor{
|
||||||
ds: ds,
|
ds: ds,
|
||||||
initState: true,
|
initState: true,
|
||||||
// cursorValid: true,
|
|
||||||
index: -1,
|
index: -1,
|
||||||
count: 0,
|
count: 0,
|
||||||
current: nil,
|
current: nil,
|
||||||
@ -39,6 +36,7 @@ func NewDataCursor(ctx ExprContext, ds map[string]Functor, resource any) (dc *da
|
|||||||
cleanFunc: ds[CleanName],
|
cleanFunc: ds[CleanName],
|
||||||
resetFunc: ds[ResetName],
|
resetFunc: ds[ResetName],
|
||||||
}
|
}
|
||||||
|
//dc.Next()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,7 +77,7 @@ func (dc *dataCursor) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (dc *dataCursor) HasOperation(name string) (exists bool) {
|
func (dc *dataCursor) HasOperation(name string) (exists bool) {
|
||||||
exists = slices.Contains([]string{CleanName, ResetName, CurrentName, IndexName}, name)
|
exists = name == IndexName
|
||||||
if !exists {
|
if !exists {
|
||||||
f, ok := dc.ds[name]
|
f, ok := dc.ds[name]
|
||||||
exists = ok && isFunctor(f)
|
exists = ok && isFunctor(f)
|
||||||
@ -90,83 +88,63 @@ func (dc *dataCursor) HasOperation(name string) (exists bool) {
|
|||||||
func (dc *dataCursor) CallOperation(name string, args map[string]any) (value any, err error) {
|
func (dc *dataCursor) CallOperation(name string, args map[string]any) (value any, err error) {
|
||||||
if name == IndexName {
|
if name == IndexName {
|
||||||
value = int64(dc.Index())
|
value = int64(dc.Index())
|
||||||
} else if name == CleanName {
|
|
||||||
err = dc.Clean()
|
|
||||||
} else if name == ResetName {
|
|
||||||
err = dc.Reset()
|
|
||||||
} else if functor, ok := dc.ds[name]; ok && isFunctor(functor) {
|
} else if functor, ok := dc.ds[name]; ok && isFunctor(functor) {
|
||||||
ctx := cloneContext(dc.ctx)
|
if functor == dc.cleanFunc {
|
||||||
value, err = functor.InvokeNamed(ctx, name, args)
|
value, err = dc.Clean()
|
||||||
exportObjects(dc.ctx, ctx)
|
} else if functor == dc.resetFunc {
|
||||||
|
value, err = dc.Reset()
|
||||||
|
} else {
|
||||||
|
ctx := cloneContext(dc.ctx)
|
||||||
|
value, err = functor.InvokeNamed(ctx, name, args)
|
||||||
|
exportObjects(dc.ctx, ctx)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
err = errNoOperation(name)
|
err = errNoOperation(name)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// func (dc *dataCursor) Reset() (err error) {
|
func (dc *dataCursor) Reset() (success bool, err error) {
|
||||||
// if dc.resetFunc != nil {
|
|
||||||
// if dc.resource != nil {
|
|
||||||
// ctx := cloneContext(dc.ctx)
|
|
||||||
// actualParams := bindActualParams(dc.resetFunc, []any{dc.resource})
|
|
||||||
// _, err = dc.resetFunc.InvokeNamed(ctx, ResetName, actualParams)
|
|
||||||
// exportObjects(dc.ctx, ctx)
|
|
||||||
// dc.index = -1
|
|
||||||
// dc.count = 0
|
|
||||||
// dc.initState = true
|
|
||||||
// dc.current = nil
|
|
||||||
// dc.lastErr = nil
|
|
||||||
// } else {
|
|
||||||
// err = errInvalidDataSource()
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// err = errNoOperation(ResetName)
|
|
||||||
// }
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
|
|
||||||
func (dc *dataCursor) Reset() (err error) {
|
|
||||||
if dc.resetFunc != nil {
|
if dc.resetFunc != nil {
|
||||||
ctx := cloneContext(dc.ctx)
|
if dc.resource != nil {
|
||||||
actualParams := bindActualParams(dc.resetFunc, []any{dc.resource})
|
ctx := cloneContext(dc.ctx)
|
||||||
_, err = dc.resetFunc.InvokeNamed(ctx, ResetName, actualParams)
|
actualParams := bindActualParams(dc.resetFunc, []any{dc.resource})
|
||||||
exportObjects(dc.ctx, ctx)
|
_, err = dc.resetFunc.InvokeNamed(ctx, ResetName, actualParams)
|
||||||
|
exportObjects(dc.ctx, ctx)
|
||||||
|
dc.index = -1
|
||||||
|
dc.count = 0
|
||||||
|
dc.initState = true
|
||||||
|
dc.current = nil
|
||||||
|
dc.lastErr = nil
|
||||||
|
//dc.Next()
|
||||||
|
} else {
|
||||||
|
err = errInvalidDataSource()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = errNoOperation(ResetName)
|
||||||
}
|
}
|
||||||
dc.index = -1
|
success = err == nil
|
||||||
dc.count = 0
|
|
||||||
dc.initState = true
|
|
||||||
dc.current = nil
|
|
||||||
dc.lastErr = nil
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dc *dataCursor) Clean() (err error) {
|
func (dc *dataCursor) Clean() (success bool, err error) {
|
||||||
if dc.cleanFunc != nil {
|
if dc.cleanFunc != nil {
|
||||||
ctx := cloneContext(dc.ctx)
|
if dc.resource != nil {
|
||||||
actualParams := bindActualParams(dc.cleanFunc, []any{dc.resource})
|
ctx := cloneContext(dc.ctx)
|
||||||
_, err = dc.cleanFunc.InvokeNamed(ctx, CleanName, actualParams)
|
actualParams := bindActualParams(dc.cleanFunc, []any{dc.resource})
|
||||||
exportObjects(dc.ctx, ctx)
|
_, err = dc.cleanFunc.InvokeNamed(ctx, CleanName, actualParams)
|
||||||
|
// dc.resource = nil
|
||||||
|
exportObjects(dc.ctx, ctx)
|
||||||
|
} else {
|
||||||
|
err = errInvalidDataSource()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = errNoOperation(CleanName)
|
||||||
}
|
}
|
||||||
dc.lastErr = io.EOF
|
success = err == nil
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// func (dc *dataCursor) Clean() (err error) {
|
|
||||||
// if dc.cleanFunc != nil {
|
|
||||||
// if dc.resource != nil {
|
|
||||||
// ctx := cloneContext(dc.ctx)
|
|
||||||
// actualParams := bindActualParams(dc.cleanFunc, []any{dc.resource})
|
|
||||||
// _, err = dc.cleanFunc.InvokeNamed(ctx, CleanName, actualParams)
|
|
||||||
// exportObjects(dc.ctx, ctx)
|
|
||||||
// } else {
|
|
||||||
// err = errInvalidDataSource()
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// err = errNoOperation(CleanName)
|
|
||||||
// }
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
|
|
||||||
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
|
||||||
dc.init()
|
dc.init()
|
||||||
|
|
||||||
@ -213,89 +191,46 @@ func (dc *dataCursor) Next() (current any, err error) { // must return io.EOF af
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
current = dc.current
|
current = dc.current
|
||||||
filter := dc.ds[FilterName]
|
if dc.resource != nil {
|
||||||
mapper := dc.ds[MapName]
|
filter := dc.ds[FilterName]
|
||||||
var item any
|
mapper := dc.ds[MapName]
|
||||||
for item == nil && dc.lastErr == nil {
|
var item any
|
||||||
ctx := cloneContext(dc.ctx)
|
for item == nil && dc.lastErr == nil {
|
||||||
dc.index++
|
ctx := cloneContext(dc.ctx)
|
||||||
|
dc.index++
|
||||||
|
|
||||||
actualParams := bindActualParams(dc.nextFunc, []any{dc.resource, dc.index})
|
actualParams := bindActualParams(dc.nextFunc, []any{dc.resource, dc.index})
|
||||||
if item, dc.lastErr = dc.nextFunc.InvokeNamed(ctx, NextName, actualParams); dc.lastErr == nil {
|
if item, dc.lastErr = dc.nextFunc.InvokeNamed(ctx, NextName, actualParams); dc.lastErr == nil {
|
||||||
if item == nil {
|
if item == nil {
|
||||||
dc.lastErr = io.EOF
|
dc.lastErr = io.EOF
|
||||||
} else {
|
} else {
|
||||||
accepted := true
|
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 {
|
||||||
|
item, dc.lastErr = dc.mapItem(mapper, item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if accepted {
|
|
||||||
dc.count++
|
|
||||||
}
|
|
||||||
if item != nil && mapper != nil {
|
|
||||||
item, dc.lastErr = dc.mapItem(mapper, item)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
exportObjects(dc.ctx, ctx)
|
||||||
}
|
}
|
||||||
exportObjects(dc.ctx, ctx)
|
dc.current = item
|
||||||
}
|
if dc.lastErr != nil {
|
||||||
dc.current = item
|
dc.index--
|
||||||
if dc.lastErr != nil {
|
dc.Clean()
|
||||||
dc.index--
|
}
|
||||||
dc.Clean()
|
} else {
|
||||||
|
dc.lastErr = errInvalidDataSource()
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// func (dc *dataCursor) Next() (current any, err error) { // must return io.EOF after the last item
|
|
||||||
// if dc.initState {
|
|
||||||
// dc.init()
|
|
||||||
// } else if err = dc.lastErr; err != nil {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// current = dc.current
|
|
||||||
// if dc.resource != nil {
|
|
||||||
// filter := dc.ds[FilterName]
|
|
||||||
// mapper := dc.ds[MapName]
|
|
||||||
// var item any
|
|
||||||
// for item == nil && dc.lastErr == nil {
|
|
||||||
// ctx := cloneContext(dc.ctx)
|
|
||||||
// dc.index++
|
|
||||||
|
|
||||||
// actualParams := bindActualParams(dc.nextFunc, []any{dc.resource, dc.index})
|
|
||||||
// if item, dc.lastErr = dc.nextFunc.InvokeNamed(ctx, NextName, actualParams); dc.lastErr == nil {
|
|
||||||
// if item == nil {
|
|
||||||
// dc.lastErr = io.EOF
|
|
||||||
// } else {
|
|
||||||
// accepted := true
|
|
||||||
// if filter != nil {
|
|
||||||
// if accepted, dc.lastErr = dc.checkFilter(filter, item); dc.lastErr != nil || !accepted {
|
|
||||||
// item = nil
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if accepted {
|
|
||||||
// dc.count++
|
|
||||||
// }
|
|
||||||
// if item != nil && mapper != nil {
|
|
||||||
// item, dc.lastErr = dc.mapItem(mapper, item)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// exportObjects(dc.ctx, ctx)
|
|
||||||
// }
|
|
||||||
// dc.current = item
|
|
||||||
// if dc.lastErr != nil {
|
|
||||||
// dc.index--
|
|
||||||
// dc.Clean()
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// dc.lastErr = errInvalidDataSource()
|
|
||||||
// }
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
|
|
||||||
func (dc *dataCursor) Index() int {
|
func (dc *dataCursor) Index() int {
|
||||||
return dc.index - 1
|
return dc.index - 1
|
||||||
}
|
}
|
||||||
|
@ -348,8 +348,8 @@ func CallFunctionByArgs(parentCtx ExprContext, name string, args []any) (result
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func CallFunctionByParams(parentCtx ExprContext, name string, actualParams map[string]any) (result any, err error) {
|
func CallFunctionByParams(parentCtx ExprContext, name string, params map[string]any) (result any, err error) {
|
||||||
//var actualParams map[string]any
|
var actualParams map[string]any
|
||||||
if info, exists := GetFuncInfo(parentCtx, name); exists {
|
if info, exists := GetFuncInfo(parentCtx, name); exists {
|
||||||
functor := info.Functor()
|
functor := info.Functor()
|
||||||
ctx := info.AllocContext(parentCtx)
|
ctx := info.AllocContext(parentCtx)
|
||||||
|
@ -33,8 +33,6 @@ type Iterator interface {
|
|||||||
|
|
||||||
type ExtIterator interface {
|
type ExtIterator interface {
|
||||||
Iterator
|
Iterator
|
||||||
Reset() error
|
|
||||||
Clean() error
|
|
||||||
HasOperation(name string) bool
|
HasOperation(name string) bool
|
||||||
CallOperation(name string, args map[string]any) (value any, err error)
|
CallOperation(name string, args map[string]any) (value any, err error)
|
||||||
}
|
}
|
||||||
|
@ -99,9 +99,7 @@ func (it *ListIterator) CallOperation(name string, args map[string]any) (v any,
|
|||||||
case NextName:
|
case NextName:
|
||||||
v, err = it.Next()
|
v, err = it.Next()
|
||||||
case ResetName:
|
case ResetName:
|
||||||
err = it.Reset()
|
v, err = it.Reset()
|
||||||
case CleanName:
|
|
||||||
err = it.Clean()
|
|
||||||
case IndexName:
|
case IndexName:
|
||||||
v = int64(it.Index())
|
v = int64(it.Index())
|
||||||
case CurrentName:
|
case CurrentName:
|
||||||
@ -149,12 +147,8 @@ func (it *ListIterator) Count() int {
|
|||||||
return it.count
|
return it.count
|
||||||
}
|
}
|
||||||
|
|
||||||
func (it *ListIterator) Reset() (error) {
|
func (it *ListIterator) Reset() (bool, error) {
|
||||||
it.index = it.start - it.step
|
it.index = it.start - it.step
|
||||||
it.count = 0
|
it.count = 0
|
||||||
return nil
|
return true, nil
|
||||||
}
|
|
||||||
|
|
||||||
func (it *ListIterator) Clean() (error) {
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,6 @@ func evalIterator(ctx ExprContext, opTerm *term) (v any, err error) {
|
|||||||
|
|
||||||
if ds != nil {
|
if ds != nil {
|
||||||
var dc *dataCursor
|
var dc *dataCursor
|
||||||
dcCtx := ctx.Clone()
|
|
||||||
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
|
var resource any
|
||||||
@ -110,10 +109,9 @@ func evalIterator(ctx ExprContext, opTerm *term) (v any, err error) {
|
|||||||
if resource, err = initFunc.InvokeNamed(initCtx, InitName, actualParams); err != nil {
|
if resource, err = initFunc.InvokeNamed(initCtx, InitName, actualParams); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
dcCtx := ctx.Clone()
|
||||||
exportObjects(dcCtx, initCtx)
|
exportObjects(dcCtx, initCtx)
|
||||||
dc = NewDataCursor(dcCtx, ds, resource)
|
dc = NewDataCursor(dcCtx, ds, resource)
|
||||||
} else {
|
|
||||||
dc = NewDataCursor(dcCtx, ds, nil)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
v = dc
|
v = dc
|
||||||
|
@ -17,7 +17,7 @@ func TestIteratorParser(t *testing.T) {
|
|||||||
/* 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},
|
||||||
/* 7 */ {`builtin "math.arith"; include "test-resources/file-reader.expr"; it=$(ds,"test-resources/int.list"); mul(it)`, int64(12000), nil},
|
/* 7 */ {`builtin "math.arith"; include "test-resources/file-reader.expr"; it=$(ds,"test-resources/int.list"); mul(it)`, int64(12000), nil},
|
||||||
/* 8 */ {`include "test-resources/file-reader.expr"; it=$(ds,"test-resources/int.list"); it++; it.index`, int64(0), nil},
|
/* 8 */ {`include "test-resources/file-reader.expr"; it=$(ds,"test-resources/int.list"); it++; it.index`, int64(0), nil},
|
||||||
/* 9 */ {`include "test-resources/file-reader.expr"; it=$(ds,"test-resources/int.list"); it.clean`, nil, nil},
|
/* 9 */ {`include "test-resources/file-reader.expr"; it=$(ds,"test-resources/int.list"); it.clean`, true, nil},
|
||||||
/* 10 */ {`it=$(1,2,3); it++`, int64(1), nil},
|
/* 10 */ {`it=$(1,2,3); it++`, int64(1), nil},
|
||||||
/* 11 */ {`it=$(1,2,3); it++; it.reset; it++`, int64(1), nil},
|
/* 11 */ {`it=$(1,2,3); it++; it.reset; it++`, int64(1), nil},
|
||||||
/* 12 */ {`it=$([1,2,3,4],1); it++`, int64(2), nil},
|
/* 12 */ {`it=$([1,2,3,4],1); it++`, int64(2), nil},
|
||||||
@ -25,10 +25,8 @@ func TestIteratorParser(t *testing.T) {
|
|||||||
/* 14 */ {`it=$([1,2,3,4],1,3,2); it++; it++;`, int64(4), nil},
|
/* 14 */ {`it=$([1,2,3,4],1,3,2); it++; it++;`, int64(4), nil},
|
||||||
/* 15 */ {`it=$([1,2,3,4],1,2,2); it++; it++;`, nil, `EOF`},
|
/* 15 */ {`it=$([1,2,3,4],1,2,2); it++; it++;`, nil, `EOF`},
|
||||||
/* 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},
|
||||||
/* 17 */ {`it=$({"next":func(){5}}); it++`, int64(5), nil},
|
|
||||||
/* 18 */ {`it=$({"next":func(){5}}); it.clean`, nil, nil},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//runTestSuiteSpec(t, section, inputs, 18)
|
// runTestSuiteSpec(t, section, inputs, 11)
|
||||||
runTestSuite(t, section, inputs)
|
runTestSuite(t, section, inputs)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user