// 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 []any) (it Iterator, op Functor, err error) { var ok bool if it, ok = args[0].(Iterator); !ok { err = fmt.Errorf("paramter %q must be an iterator, passed %v [%s]", ParamIterator, args[0], TypeName(args[0])) return } if len(args) > 1 { if op, ok = args[1].(Functor); !ok || op == nil { err = fmt.Errorf("paramter %q must be a function, passed %v [%s]", iterParamOperator, args[1], TypeName(args[1])) return } if len(args) > 2 { var vars *DictType if vars, ok = args[2].(*DictType); !ok || vars == nil { err = fmt.Errorf("paramter %q must be a dictionary, passed %v [%s]", iterParamVars, args[2], TypeName(args[2])) return } 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 []any) (result any, err error) { var it Iterator var ok bool var op Functor var v any var usingDefaultOp = false var params []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 = []any{item} } else { params = []any{it.Index(), item} } if v, err = op.Invoke(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") }