133 lines
2.6 KiB
Go
133 lines
2.6 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"
|
|
)
|
|
|
|
type IterIter struct {
|
|
it kern.Iterator
|
|
count int64
|
|
index int64
|
|
ctx kern.ExprContext
|
|
op kern.Functor
|
|
opName string
|
|
args map[string]any
|
|
current any
|
|
}
|
|
|
|
func NewIterIter(it kern.Iterator, ctx kern.ExprContext, op kern.Functor, args map[string]any) (iter kern.Iterator, err error) {
|
|
var opName string
|
|
if op != nil {
|
|
if f := op.GetFunc(); f != nil {
|
|
opName = f.Name()
|
|
// } else {
|
|
// return nil, fmt.Errorf("invalid functor argument for iter-iter: expected kern.Functor, got %T", args["op"])
|
|
}
|
|
}
|
|
if len(opName) == 0 {
|
|
opName = "anonymous"
|
|
}
|
|
iter = &IterIter{it: it, count: 0, index: -1, ctx: ctx, op: op, opName: opName, args: args}
|
|
|
|
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 HasStandardOperation(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 it.op != nil {
|
|
if item, err = it.op.InvokeNamed(it.ctx, it.opName, it.args); err == nil {
|
|
it.current = item
|
|
}
|
|
} 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
|
|
}
|