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