new iter-iter iterator and kern.func-info module

This commit is contained in:
2026-05-05 20:38:30 +02:00
parent 7f34ccf955
commit acd4f8487d
30 changed files with 527 additions and 485 deletions
+132
View File
@@ -0,0 +1,132 @@
// 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
}