105 lines
2.5 KiB
Go
105 lines
2.5 KiB
Go
// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
|
|
// All rights reserved.
|
|
|
|
// builtin-iterator.go
|
|
package expr
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
)
|
|
|
|
const (
|
|
iterParamOperator = "operator"
|
|
iterParamVars = "vars"
|
|
iterVarStatus = "status"
|
|
)
|
|
|
|
func parseRunArgs(localCtx ExprContext, args map[string]any) (it Iterator, op Functor, err error) {
|
|
var ok bool
|
|
|
|
if it, ok = args[ParamIterator].(Iterator); !ok {
|
|
err = fmt.Errorf("paramter %q must be an iterator, passed %v [%s]", ParamIterator, args[ParamIterator], TypeName(args[ParamIterator]))
|
|
return
|
|
}
|
|
|
|
if op, ok = args[iterParamOperator].(Functor); !ok && args[iterParamOperator] != nil {
|
|
err = fmt.Errorf("paramter %q must be a function, passed %v [%s]", iterParamOperator, args[iterParamOperator], TypeName(args[iterParamOperator]))
|
|
return
|
|
}
|
|
|
|
var vars *DictType
|
|
if vars, ok = args[iterParamVars].(*DictType); !ok && args[iterParamVars] != nil {
|
|
err = fmt.Errorf("paramter %q must be a dictionary, passed %v [%s]", iterParamVars, args[iterParamVars], TypeName(args[iterParamVars]))
|
|
return
|
|
}
|
|
|
|
if vars != nil {
|
|
for key, value := range *vars {
|
|
var varName string
|
|
if varName, ok = key.(string); ok {
|
|
localCtx.UnsafeSetVar(varName, value)
|
|
}
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func runFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
|
var it Iterator
|
|
var ok bool
|
|
var op Functor
|
|
var v any
|
|
var usingDefaultOp = false
|
|
var params map[string]any
|
|
var item any
|
|
|
|
localCtx := ctx.Clone()
|
|
localCtx.UnsafeSetVar(iterVarStatus, nil)
|
|
|
|
if it, op, err = parseRunArgs(localCtx, args); err != nil {
|
|
return
|
|
} else if op == nil {
|
|
op = NewGolangFunctor(printLnFunc)
|
|
usingDefaultOp = true
|
|
}
|
|
|
|
for item, err = it.Next(); err == nil; item, err = it.Next() {
|
|
if usingDefaultOp {
|
|
params = map[string]any{ParamItem: []any{item}}
|
|
} else {
|
|
params = map[string]any{ParamIndex: it.Index(), ParamItem: item}
|
|
}
|
|
|
|
if v, err = op.InvokeNamed(localCtx, iterParamOperator, params); err != nil {
|
|
break
|
|
} else {
|
|
var success bool
|
|
if success, ok = ToBool(v); !success || !ok {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
if err == io.EOF {
|
|
err = nil
|
|
}
|
|
if err == nil {
|
|
result, _ = localCtx.GetVar(iterVarStatus)
|
|
}
|
|
return
|
|
}
|
|
|
|
func ImportIterFuncs(ctx ExprContext) {
|
|
ctx.RegisterFunc("run", NewGolangFunctor(runFunc), TypeAny, []ExprFuncParam{
|
|
NewFuncParam(ParamIterator),
|
|
NewFuncParamFlag(iterParamOperator, PfOptional),
|
|
NewFuncParamFlag(iterParamVars, PfOptional),
|
|
})
|
|
}
|
|
|
|
func init() {
|
|
RegisterBuiltinModule("iterator", ImportIterFuncs, "Iterator helper functions")
|
|
}
|