// 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 = NewGolangFunctor2(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", NewGolangFunctor2(runFunc), TypeAny, []ExprFuncParam{ NewFuncParam(ParamIterator), NewFuncParamFlag(iterParamOperator, PfOptional), NewFuncParamFlag(iterParamVars, PfOptional), }) } func init() { RegisterBuiltinModule("iterator", ImportIterFuncs, "Iterator helper functions") }