From 20dc5024380b33aabf176ee70e7b2d08377b2874 Mon Sep 17 00:00:00 2001 From: Celestino Amoroso Date: Sat, 25 Apr 2026 06:25:39 +0200 Subject: [PATCH] new operator 'digest' --- operator-digest.go | 70 ++++++++++++++++++++++++++++++++++++++++++++++ symbol-map.go | 14 +++++----- symbol.go | 4 +-- 3 files changed, 79 insertions(+), 9 deletions(-) create mode 100644 operator-digest.go diff --git a/operator-digest.go b/operator-digest.go new file mode 100644 index 0000000..de7c6e8 --- /dev/null +++ b/operator-digest.go @@ -0,0 +1,70 @@ +// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com). +// All rights reserved. + +// operator-digest.go +package expr + +import ( + "fmt" + "io" +) + +//-------- map term + +func newDigestTerm(tk *Token) (inst *term) { + return &term{ + tk: *tk, + children: make([]*term, 0, 2), + position: posInfix, + priority: priIterOp, + evalFunc: evalDigest, + } +} + +func evalDigest(ctx ExprContext, opTerm *term) (v any, err error) { + var leftValue, rightValue any + var it Iterator + var item, lastValue 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)) + } + + lastValue = nil + 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 rightValue == nil { + break + } else { + lastValue = rightValue + } + } + ctx.DeleteVar("_count") + ctx.DeleteVar("_index") + ctx.DeleteVar("_") + if err != nil { + break + } + } + if err == io.EOF { + err = nil + } + v = lastValue + return +} + +// init +func init() { + registerTermConstructor(SymKwDigest, newDigestTerm) +} diff --git a/symbol-map.go b/symbol-map.go index a5b175c..2215983 100644 --- a/symbol-map.go +++ b/symbol-map.go @@ -131,13 +131,13 @@ func init() { // // SymClosedComment // 0: '*/' // // SymOneLineComment // 0: '//' // keywordBase - SymKwAnd: {"and", symClassOperator, posInfix}, - SymKwNot: {"not", symClassOperator, posInfix}, - SymKwOr: {"or", symClassOperator, posInfix}, - SymKwBut: {"but", symClassOperator, posInfix}, - SymKwMap: {"map", symClassOperator, posInfix}, - SymKwFilter: {"filter", symClassOperator, posInfix}, - // SymKwDigest: {"digest", symClassOperator, posInfix}, + SymKwAnd: {"and", symClassOperator, posInfix}, + SymKwNot: {"not", symClassOperator, posInfix}, + SymKwOr: {"or", symClassOperator, posInfix}, + SymKwBut: {"but", symClassOperator, posInfix}, + SymKwMap: {"map", symClassOperator, posInfix}, + SymKwFilter: {"filter", symClassOperator, posInfix}, + SymKwDigest: {"digest", symClassOperator, posInfix}, SymKwFunc: {"func(", symClassDeclaration, posPrefix}, SymKwBuiltin: {"builtin", symClassOperator, posPrefix}, SymKwPlugin: {"plugin", symClassOperator, posPrefix}, diff --git a/symbol.go b/symbol.go index a395136..4583335 100644 --- a/symbol.go +++ b/symbol.go @@ -121,7 +121,7 @@ const ( SymKwInclude SymKwMap SymKwFilter - // SymKwDigest + SymKwDigest SymKwNil SymKwUnset ) @@ -144,6 +144,6 @@ func init() { "OR": SymKwOr, "NIL": SymKwNil, "UNSET": SymKwUnset, - // "DIGEST": SymKwDigest, + "DIGEST": SymKwDigest, } }