// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com). // All rights reserved. // operator-filter.go package expr import ( "fmt" "io" ) //-------- map term func newFilterTerm(tk *Token) (inst *term) { return &term{ tk: *tk, children: make([]*term, 0, 2), position: posInfix, priority: priIterOp, evalFunc: evalFilter, } } func evalFilter(ctx ExprContext, opTerm *term) (v any, err error) { var leftValue, rightValue any var it Iterator var item any if err = opTerm.checkOperands(); err != nil { return } if leftValue, err = opTerm.children[0].compute(ctx); err != nil { return } if it, err = NewIterator(leftValue); err != nil { return nil, fmt.Errorf("left operand of MAP must be an iterable data-source; got %s", TypeName(leftValue)) } values := newListA() for item, err = it.Next(); err == nil; item, err = it.Next() { ctx.SetVar("_", item) ctx.SetVar("_index", it.Index()) ctx.SetVar("_count", it.Count()) if rightValue, err = opTerm.children[1].compute(ctx); err == nil { if success, valid := ToBool(rightValue); valid { if success { values.appendItem(item) } } else { err = fmt.Errorf("filter expression must return a boolean or a castable to boolean, got %v [%T]", rightValue, rightValue) } } ctx.DeleteVar("_count") ctx.DeleteVar("_index") ctx.DeleteVar("_") if err != nil { break } } if err == io.EOF { err = nil } v = values return } // init func init() { registerTermConstructor(SymKwFilter, newFilterTerm) }