128 lines
2.5 KiB
Go
128 lines
2.5 KiB
Go
// Copyright (c) 2024-2026 Celestino Amoroso (celestino.amoroso@gmail.com).
|
|
// All rights reserved.
|
|
|
|
// iter-iter.go
|
|
package expr
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
|
|
"git.portale-stac.it/go-pkg/expr/kern"
|
|
"git.portale-stac.it/go-pkg/expr/scan"
|
|
)
|
|
|
|
type IterIter struct {
|
|
it kern.Iterator
|
|
count int64
|
|
index int64
|
|
ctx kern.ExprContext
|
|
exprList []*scan.Term
|
|
current any
|
|
}
|
|
|
|
func NewIterIter(it kern.Iterator, ctx kern.ExprContext, exprs []*scan.Term) (iter kern.Iterator, err error) {
|
|
iter = &IterIter{it: it, count: 0, index: -1, ctx: ctx, exprList: exprs, current: nil}
|
|
return
|
|
}
|
|
|
|
func (it *IterIter) String() string {
|
|
return fmt.Sprintf("$(%s)", it.it)
|
|
}
|
|
|
|
func (it *IterIter) TypeName() string {
|
|
return "IterIter"
|
|
}
|
|
|
|
func (it *IterIter) HasOperation(name string) bool {
|
|
return HasIterStandardOperations(name)
|
|
}
|
|
|
|
func (it *IterIter) CallOperation(name string, args map[string]any) (v any, err error) {
|
|
switch name {
|
|
case kern.NextName:
|
|
v, err = it.Next()
|
|
case kern.ResetName:
|
|
err = it.Reset()
|
|
case kern.CleanName:
|
|
err = it.Clean()
|
|
case kern.IndexName:
|
|
v = int64(it.Index())
|
|
case kern.CurrentName:
|
|
v, err = it.Current()
|
|
case kern.CountName:
|
|
v = it.count
|
|
default:
|
|
err = kern.ErrNoOperation(name)
|
|
}
|
|
return
|
|
}
|
|
|
|
func (it *IterIter) Current() (item any, err error) {
|
|
if it.current != nil {
|
|
item = it.current
|
|
} else if len(it.exprList) > 0 {
|
|
// Evaluate the expression list and use the result as the current item
|
|
var exprValue any
|
|
for _, expr := range it.exprList {
|
|
if exprValue, err = expr.Compute(it.ctx); err != nil {
|
|
break
|
|
}
|
|
it.ctx.UnsafeSetVar(kern.ControlLastResult, exprValue)
|
|
}
|
|
if err == nil {
|
|
item = exprValue
|
|
}
|
|
} else {
|
|
var exists bool
|
|
if it.current, exists = it.ctx.GetVar("_"); !exists {
|
|
err = fmt.Errorf("current item not available")
|
|
} else {
|
|
item = it.current
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (it *IterIter) Next() (item any, err error) {
|
|
var src any
|
|
|
|
it.current = nil
|
|
ctx := it.ctx
|
|
for src, err = it.it.Next(); src == nil && err == nil; src, err = it.it.Next() {
|
|
}
|
|
|
|
if err == nil {
|
|
if src == nil {
|
|
err = io.EOF
|
|
} else {
|
|
ctx.UnsafeSetVar("_", src)
|
|
ctx.UnsafeSetVar("__", it.it.Index())
|
|
ctx.UnsafeSetVar("_#", it.it.Count())
|
|
item, err = it.Current()
|
|
ctx.DeleteVar("_#")
|
|
ctx.DeleteVar("__")
|
|
ctx.DeleteVar("_")
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (it *IterIter) Index() int64 {
|
|
return it.index
|
|
}
|
|
|
|
func (it *IterIter) Count() int64 {
|
|
return it.count
|
|
}
|
|
|
|
func (it *IterIter) Reset() error {
|
|
it.index = -1
|
|
it.count = 0
|
|
return nil
|
|
}
|
|
|
|
func (it *IterIter) Clean() error {
|
|
return nil
|
|
}
|