new iter-iter iterator and kern.func-info module

This commit is contained in:
2026-05-05 20:38:30 +02:00
parent 7f34ccf955
commit acd4f8487d
30 changed files with 527 additions and 485 deletions
+10 -10
View File
@@ -272,7 +272,7 @@ func setFunc(ctx kern.ExprContext, name string, args map[string]any) (result any
func ImportBuiltinsFuncs(ctx kern.ExprContext) { func ImportBuiltinsFuncs(ctx kern.ExprContext) {
anyParams := []kern.ExprFuncParam{ anyParams := []kern.ExprFuncParam{
NewFuncParam(kern.ParamValue), kern.NewFuncParam(kern.ParamValue),
} }
ctx.RegisterFunc("isNil", kern.NewGolangFunctor(isNilFunc), kern.TypeBoolean, anyParams) ctx.RegisterFunc("isNil", kern.NewGolangFunctor(isNilFunc), kern.TypeBoolean, anyParams)
@@ -290,27 +290,27 @@ func ImportBuiltinsFuncs(ctx kern.ExprContext) {
ctx.RegisterFunc("dec", kern.NewGolangFunctor(decFunc), kern.TypeFloat, anyParams) ctx.RegisterFunc("dec", kern.NewGolangFunctor(decFunc), kern.TypeFloat, anyParams)
ctx.RegisterFunc("string", kern.NewGolangFunctor(stringFunc), kern.TypeString, anyParams) ctx.RegisterFunc("string", kern.NewGolangFunctor(stringFunc), kern.TypeString, anyParams)
ctx.RegisterFunc("fract", kern.NewGolangFunctor(fractFunc), kern.TypeFraction, []kern.ExprFuncParam{ ctx.RegisterFunc("fract", kern.NewGolangFunctor(fractFunc), kern.TypeFraction, []kern.ExprFuncParam{
NewFuncParam(kern.ParamValue), kern.NewFuncParam(kern.ParamValue),
NewFuncParamFlagDef(ParamDenominator, PfDefault, int64(1)), kern.NewFuncParamFlagDef(ParamDenominator, kern.PfDefault, int64(1)),
}) })
ctx.RegisterFunc("eval", kern.NewGolangFunctor(evalFunc), kern.TypeAny, []kern.ExprFuncParam{ ctx.RegisterFunc("eval", kern.NewGolangFunctor(evalFunc), kern.TypeAny, []kern.ExprFuncParam{
NewFuncParam(kern.ParamSource), kern.NewFuncParam(kern.ParamSource),
}) })
ctx.RegisterFunc("var", kern.NewGolangFunctor(varFunc), kern.TypeAny, []kern.ExprFuncParam{ ctx.RegisterFunc("var", kern.NewGolangFunctor(varFunc), kern.TypeAny, []kern.ExprFuncParam{
NewFuncParam(kern.ParamName), kern.NewFuncParam(kern.ParamName),
NewFuncParamFlagDef(kern.ParamValue, PfDefault, nil), kern.NewFuncParamFlagDef(kern.ParamValue, kern.PfDefault, nil),
}) })
ctx.RegisterFunc("set", kern.NewGolangFunctor(setFunc), kern.TypeAny, []kern.ExprFuncParam{ ctx.RegisterFunc("set", kern.NewGolangFunctor(setFunc), kern.TypeAny, []kern.ExprFuncParam{
NewFuncParam(kern.ParamName), kern.NewFuncParam(kern.ParamName),
NewFuncParam(kern.ParamValue), kern.NewFuncParam(kern.ParamValue),
}) })
// ctx.RegisterFunc("unset", kern.NewGolangFunctor(unsetFunc), kern.TypeAny, []kern.ExprFuncParam{ // ctx.RegisterFunc("unset", kern.NewGolangFunctor(unsetFunc), kern.TypeAny, []kern.ExprFuncParam{
// NewFuncParam(kern.ParamName), // kern.NewFuncParam(kern.ParamName),
// NewFuncParam(kern.ParamValue), // kern.NewFuncParam(kern.ParamValue),
// }) // })
} }
+2 -2
View File
@@ -47,10 +47,10 @@ func printLnFunc(ctx kern.ExprContext, name string, args map[string]any) (result
func ImportFmtFuncs(ctx kern.ExprContext) { func ImportFmtFuncs(ctx kern.ExprContext) {
ctx.RegisterFunc("print", kern.NewGolangFunctor(printFunc), kern.TypeInt, []kern.ExprFuncParam{ ctx.RegisterFunc("print", kern.NewGolangFunctor(printFunc), kern.TypeInt, []kern.ExprFuncParam{
NewFuncParamFlag(kern.ParamItem, PfRepeat), kern.NewFuncParamFlag(kern.ParamItem, kern.PfRepeat),
}) })
ctx.RegisterFunc("println", kern.NewGolangFunctor(printLnFunc), kern.TypeInt, []kern.ExprFuncParam{ ctx.RegisterFunc("println", kern.NewGolangFunctor(printLnFunc), kern.TypeInt, []kern.ExprFuncParam{
NewFuncParamFlag(kern.ParamItem, PfRepeat), kern.NewFuncParamFlag(kern.ParamItem, kern.PfRepeat),
}) })
} }
+2 -2
View File
@@ -69,10 +69,10 @@ func doImport(ctx kern.ExprContext, name string, dirList []string, it kern.Itera
func ImportImportFuncs(ctx kern.ExprContext) { func ImportImportFuncs(ctx kern.ExprContext) {
ctx.RegisterFunc("import", kern.NewGolangFunctor(importFunc), kern.TypeAny, []kern.ExprFuncParam{ ctx.RegisterFunc("import", kern.NewGolangFunctor(importFunc), kern.TypeAny, []kern.ExprFuncParam{
NewFuncParamFlag(kern.ParamFilepath, PfRepeat), kern.NewFuncParamFlag(kern.ParamFilepath, kern.PfRepeat),
}) })
ctx.RegisterFunc("importAll", kern.NewGolangFunctor(importAllFunc), kern.TypeAny, []kern.ExprFuncParam{ ctx.RegisterFunc("importAll", kern.NewGolangFunctor(importAllFunc), kern.TypeAny, []kern.ExprFuncParam{
NewFuncParamFlag(kern.ParamFilepath, PfRepeat), kern.NewFuncParamFlag(kern.ParamFilepath, kern.PfRepeat),
}) })
} }
+3 -3
View File
@@ -94,9 +94,9 @@ func runFunc(ctx kern.ExprContext, name string, args map[string]any) (result any
func ImportIterFuncs(ctx kern.ExprContext) { func ImportIterFuncs(ctx kern.ExprContext) {
ctx.RegisterFunc("run", kern.NewGolangFunctor(runFunc), kern.TypeAny, []kern.ExprFuncParam{ ctx.RegisterFunc("run", kern.NewGolangFunctor(runFunc), kern.TypeAny, []kern.ExprFuncParam{
NewFuncParam(kern.ParamIterator), kern.NewFuncParam(kern.ParamIterator),
NewFuncParamFlag(iterParamOperator, PfOptional), kern.NewFuncParamFlag(iterParamOperator, kern.PfOptional),
NewFuncParamFlag(iterParamVars, PfOptional), kern.NewFuncParamFlag(iterParamVars, kern.PfOptional),
}) })
} }
+2 -2
View File
@@ -172,11 +172,11 @@ func mulFunc(ctx kern.ExprContext, name string, args map[string]any) (result any
func ImportMathFuncs(ctx kern.ExprContext) { func ImportMathFuncs(ctx kern.ExprContext) {
ctx.RegisterFunc("add", kern.NewGolangFunctor(addFunc), kern.TypeNumber, []kern.ExprFuncParam{ ctx.RegisterFunc("add", kern.NewGolangFunctor(addFunc), kern.TypeNumber, []kern.ExprFuncParam{
NewFuncParamFlagDef(kern.ParamValue, PfDefault|PfRepeat, int64(0)), kern.NewFuncParamFlagDef(kern.ParamValue, kern.PfDefault|kern.PfRepeat, int64(0)),
}) })
ctx.RegisterFunc("mul", kern.NewGolangFunctor(mulFunc), kern.TypeNumber, []kern.ExprFuncParam{ ctx.RegisterFunc("mul", kern.NewGolangFunctor(mulFunc), kern.TypeNumber, []kern.ExprFuncParam{
NewFuncParamFlagDef(kern.ParamValue, PfDefault|PfRepeat, int64(1)), kern.NewFuncParamFlagDef(kern.ParamValue, kern.PfDefault|kern.PfRepeat, int64(1)),
}) })
} }
+10 -10
View File
@@ -224,37 +224,37 @@ func fileReadTextAllFunc(ctx kern.ExprContext, name string, args map[string]any)
func ImportOsFuncs(ctx kern.ExprContext) { func ImportOsFuncs(ctx kern.ExprContext) {
ctx.RegisterFunc("fileOpen", kern.NewGolangFunctor(openFileFunc), kern.TypeFileHandle, []kern.ExprFuncParam{ ctx.RegisterFunc("fileOpen", kern.NewGolangFunctor(openFileFunc), kern.TypeFileHandle, []kern.ExprFuncParam{
NewFuncParam(kern.ParamFilepath), kern.NewFuncParam(kern.ParamFilepath),
}) })
ctx.RegisterFunc("fileAppend", kern.NewGolangFunctor(appendFileFunc), kern.TypeFileHandle, []kern.ExprFuncParam{ ctx.RegisterFunc("fileAppend", kern.NewGolangFunctor(appendFileFunc), kern.TypeFileHandle, []kern.ExprFuncParam{
NewFuncParam(kern.ParamFilepath), kern.NewFuncParam(kern.ParamFilepath),
}) })
ctx.RegisterFunc("fileCreate", kern.NewGolangFunctor(createFileFunc), kern.TypeFileHandle, []kern.ExprFuncParam{ ctx.RegisterFunc("fileCreate", kern.NewGolangFunctor(createFileFunc), kern.TypeFileHandle, []kern.ExprFuncParam{
NewFuncParam(kern.ParamFilepath), kern.NewFuncParam(kern.ParamFilepath),
}) })
ctx.RegisterFunc("fileClose", kern.NewGolangFunctor(closeFileFunc), kern.TypeBoolean, []kern.ExprFuncParam{ ctx.RegisterFunc("fileClose", kern.NewGolangFunctor(closeFileFunc), kern.TypeBoolean, []kern.ExprFuncParam{
NewFuncParam(kern.ParamHandle), kern.NewFuncParam(kern.ParamHandle),
}) })
ctx.RegisterFunc("fileWriteText", kern.NewGolangFunctor(fileWriteTextFunc), kern.TypeInt, []kern.ExprFuncParam{ ctx.RegisterFunc("fileWriteText", kern.NewGolangFunctor(fileWriteTextFunc), kern.TypeInt, []kern.ExprFuncParam{
NewFuncParam(kern.ParamHandle), kern.NewFuncParam(kern.ParamHandle),
NewFuncParamFlagDef(kern.ParamItem, PfDefault|PfRepeat, ""), kern.NewFuncParamFlagDef(kern.ParamItem, kern.PfDefault|kern.PfRepeat, ""),
}) })
ctx.RegisterFunc("fileReadText", kern.NewGolangFunctor(fileReadTextFunc), kern.TypeString, []kern.ExprFuncParam{ ctx.RegisterFunc("fileReadText", kern.NewGolangFunctor(fileReadTextFunc), kern.TypeString, []kern.ExprFuncParam{
NewFuncParam(kern.ParamHandle), kern.NewFuncParam(kern.ParamHandle),
NewFuncParamFlagDef(osLimitCh, PfDefault, "\n"), kern.NewFuncParamFlagDef(osLimitCh, kern.PfDefault, "\n"),
}) })
ctx.RegisterFunc("fileReadTextAll", kern.NewGolangFunctor(fileReadTextAllFunc), kern.TypeString, []kern.ExprFuncParam{ ctx.RegisterFunc("fileReadTextAll", kern.NewGolangFunctor(fileReadTextAllFunc), kern.TypeString, []kern.ExprFuncParam{
NewFuncParam(kern.ParamHandle), kern.NewFuncParam(kern.ParamHandle),
}) })
ctx.RegisterFunc("fileReadIterator", kern.NewGolangFunctor(fileReadIteratorFunc), kern.TypeIterator, []kern.ExprFuncParam{ ctx.RegisterFunc("fileReadIterator", kern.NewGolangFunctor(fileReadIteratorFunc), kern.TypeIterator, []kern.ExprFuncParam{
NewFuncParam(paramHandleOrPath), kern.NewFuncParam(paramHandleOrPath),
}) })
} }
+17 -17
View File
@@ -225,44 +225,44 @@ func lowerStrFunc(ctx kern.ExprContext, name string, args map[string]any) (resul
// Import above functions in the context // Import above functions in the context
func ImportStringFuncs(ctx kern.ExprContext) { func ImportStringFuncs(ctx kern.ExprContext) {
ctx.RegisterFunc("strJoin", kern.NewGolangFunctor(joinStrFunc), kern.TypeString, []kern.ExprFuncParam{ ctx.RegisterFunc("strJoin", kern.NewGolangFunctor(joinStrFunc), kern.TypeString, []kern.ExprFuncParam{
NewFuncParam(kern.ParamSeparator), kern.NewFuncParam(kern.ParamSeparator),
NewFuncParamFlag(kern.ParamItem, PfRepeat), kern.NewFuncParamFlag(kern.ParamItem, kern.PfRepeat),
}) })
ctx.RegisterFunc("strSub", kern.NewGolangFunctor(subStrFunc), kern.TypeString, []kern.ExprFuncParam{ ctx.RegisterFunc("strSub", kern.NewGolangFunctor(subStrFunc), kern.TypeString, []kern.ExprFuncParam{
NewFuncParam(kern.ParamSource), kern.NewFuncParam(kern.ParamSource),
NewFuncParamFlagDef(kern.ParamStart, PfDefault, int64(0)), kern.NewFuncParamFlagDef(kern.ParamStart, kern.PfDefault, int64(0)),
NewFuncParamFlagDef(kern.ParamCount, PfDefault, int64(-1)), kern.NewFuncParamFlagDef(kern.ParamCount, kern.PfDefault, int64(-1)),
}) })
ctx.RegisterFunc("strSplit", kern.NewGolangFunctor(splitStrFunc), "list of "+kern.TypeString, []kern.ExprFuncParam{ ctx.RegisterFunc("strSplit", kern.NewGolangFunctor(splitStrFunc), "list of "+kern.TypeString, []kern.ExprFuncParam{
NewFuncParam(kern.ParamSource), kern.NewFuncParam(kern.ParamSource),
NewFuncParamFlagDef(kern.ParamSeparator, PfDefault, ""), kern.NewFuncParamFlagDef(kern.ParamSeparator, kern.PfDefault, ""),
NewFuncParamFlagDef(kern.ParamCount, PfDefault, int64(-1)), kern.NewFuncParamFlagDef(kern.ParamCount, kern.PfDefault, int64(-1)),
}) })
ctx.RegisterFunc("strTrim", kern.NewGolangFunctor(trimStrFunc), kern.TypeString, []kern.ExprFuncParam{ ctx.RegisterFunc("strTrim", kern.NewGolangFunctor(trimStrFunc), kern.TypeString, []kern.ExprFuncParam{
NewFuncParam(kern.ParamSource), kern.NewFuncParam(kern.ParamSource),
}) })
ctx.RegisterFunc("strStartsWith", kern.NewGolangFunctor(startsWithStrFunc), kern.TypeBoolean, []kern.ExprFuncParam{ ctx.RegisterFunc("strStartsWith", kern.NewGolangFunctor(startsWithStrFunc), kern.TypeBoolean, []kern.ExprFuncParam{
NewFuncParam(kern.ParamSource), kern.NewFuncParam(kern.ParamSource),
NewFuncParam(kern.ParamPrefix), kern.NewFuncParam(kern.ParamPrefix),
NewFuncParamFlag(strParamOther, PfRepeat), kern.NewFuncParamFlag(strParamOther, kern.PfRepeat),
}) })
ctx.RegisterFunc("strEndsWith", kern.NewGolangFunctor(endsWithStrFunc), kern.TypeBoolean, []kern.ExprFuncParam{ ctx.RegisterFunc("strEndsWith", kern.NewGolangFunctor(endsWithStrFunc), kern.TypeBoolean, []kern.ExprFuncParam{
NewFuncParam(kern.ParamSource), kern.NewFuncParam(kern.ParamSource),
NewFuncParam(kern.ParamSuffix), kern.NewFuncParam(kern.ParamSuffix),
NewFuncParamFlag(strParamOther, PfRepeat), kern.NewFuncParamFlag(strParamOther, kern.PfRepeat),
}) })
ctx.RegisterFunc("strUpper", kern.NewGolangFunctor(upperStrFunc), kern.TypeString, []kern.ExprFuncParam{ ctx.RegisterFunc("strUpper", kern.NewGolangFunctor(upperStrFunc), kern.TypeString, []kern.ExprFuncParam{
NewFuncParam(kern.ParamSource), kern.NewFuncParam(kern.ParamSource),
}) })
ctx.RegisterFunc("strLower", kern.NewGolangFunctor(lowerStrFunc), kern.TypeString, []kern.ExprFuncParam{ ctx.RegisterFunc("strLower", kern.NewGolangFunctor(lowerStrFunc), kern.TypeString, []kern.ExprFuncParam{
NewFuncParam(kern.ParamSource), kern.NewFuncParam(kern.ParamSource),
}) })
} }
+5 -3
View File
@@ -116,8 +116,11 @@ func NewDictIterator(dict *kern.DictType, args []any) (it *DictIterator, err err
} }
} }
dictIt.makeKeys(*dict, sortType) if err == nil {
return dictIt, err dictIt.makeKeys(*dict, sortType)
it = dictIt
}
return
} }
func NewMapIterator(m map[any]any) (it *DictIterator) { func NewMapIterator(m map[any]any) (it *DictIterator) {
@@ -139,7 +142,6 @@ func (it *DictIterator) TypeName() string {
} }
func (it *DictIterator) HasOperation(name string) bool { func (it *DictIterator) HasOperation(name string) bool {
// yes := name == NextName || name == ResetName || name == IndexName || name == CountName || name == CurrentName
yes := slices.Contains([]string{kern.NextName, kern.ResetName, kern.IndexName, kern.CountName, kern.CurrentName, kern.CleanName, kern.KeyName, kern.ValueName}, name) yes := slices.Contains([]string{kern.NextName, kern.ResetName, kern.IndexName, kern.CountName, kern.CurrentName, kern.CleanName, kern.KeyName, kern.ValueName}, name)
return yes return yes
} }
-388
View File
@@ -1,388 +0,0 @@
// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
// All rights reserved.
// function.go
package expr
import (
"fmt"
"strings"
"git.portale-stac.it/go-pkg/expr/kern"
"git.portale-stac.it/go-pkg/expr/scan"
)
// ---- Function template
// type FuncTemplate func(ctx expr.ExprContext, name string, args map[string]any) (result any, err error)
// ---- Common functor definition
type BaseFunctor struct {
info kern.ExprFunc
}
func (functor *BaseFunctor) ToString(opt kern.FmtOpt) (s string) {
if functor.info != nil {
s = functor.info.ToString(opt)
} else {
s = "func(){}"
}
return s
}
func (functor *BaseFunctor) GetParams() (params []kern.ExprFuncParam) {
if functor.info != nil {
return functor.info.Params()
} else {
return []kern.ExprFuncParam{}
}
}
func (functor *BaseFunctor) SetFunc(info kern.ExprFunc) {
functor.info = info
}
func (functor *BaseFunctor) GetFunc() kern.ExprFunc {
return functor.info
}
func (functor *BaseFunctor) GetDefinitionContext() kern.ExprContext {
return nil
}
// ---- Function Parameters
type paramFlags uint16
const (
PfDefault paramFlags = 1 << iota
PfOptional
PfRepeat
)
type funcParamInfo struct {
name string
flags paramFlags
defaultValue any
}
func NewFuncParam(name string) kern.ExprFuncParam {
return &funcParamInfo{name: name}
}
func NewFuncParamFlag(name string, flags paramFlags) kern.ExprFuncParam {
return &funcParamInfo{name: name, flags: flags}
}
func NewFuncParamFlagDef(name string, flags paramFlags, defValue any) *funcParamInfo {
return &funcParamInfo{name: name, flags: flags, defaultValue: defValue}
}
func (param *funcParamInfo) Name() string {
return param.name
}
func (param *funcParamInfo) Type() string {
return kern.TypeAny
}
func (param *funcParamInfo) IsDefault() bool {
return (param.flags & PfDefault) != 0
}
func (param *funcParamInfo) IsOptional() bool {
return (param.flags & PfOptional) != 0
}
func (param *funcParamInfo) IsRepeat() bool {
return (param.flags & PfRepeat) != 0
}
func (param *funcParamInfo) DefaultValue() any {
return param.defaultValue
}
// --- Functions
// funcInfo implements expr.ExprFunc
type funcInfo struct {
name string
minArgs int
maxArgs int
functor kern.Functor
formalParams []kern.ExprFuncParam
returnType string
}
func newFuncInfo(name string, functor kern.Functor, returnType string, params []kern.ExprFuncParam) (info *funcInfo, err error) {
var minArgs = 0
var maxArgs = 0
for _, p := range params {
if maxArgs == -1 {
return nil, fmt.Errorf("no more params can be specified after the ellipsis symbol: %q", p.Name())
}
if p.IsDefault() || p.IsOptional() {
maxArgs++
} else if maxArgs == minArgs {
minArgs++
maxArgs++
} else {
return nil, fmt.Errorf("can't specify non-optional param after optional ones: %q", p.Name())
}
if p.IsRepeat() {
minArgs--
maxArgs = -1
}
}
info = &funcInfo{
name: name, minArgs: minArgs, maxArgs: maxArgs, functor: functor, returnType: returnType, formalParams: params,
}
functor.SetFunc(info)
return info, nil
}
func (info *funcInfo) Params() []kern.ExprFuncParam {
return info.formalParams
}
func (info *funcInfo) ReturnType() string {
return info.returnType
}
func (info *funcInfo) ToString(opt kern.FmtOpt) string {
var sb strings.Builder
if len(info.Name()) == 0 {
sb.WriteString("func")
} else {
sb.WriteString(info.Name())
}
sb.WriteByte('(')
if info.formalParams != nil {
for i, p := range info.formalParams {
if i > 0 {
sb.WriteString(", ")
}
sb.WriteString(p.Name())
if p.IsDefault() {
sb.WriteByte('=')
if s, ok := p.DefaultValue().(string); ok {
sb.WriteByte('"')
sb.WriteString(s)
sb.WriteByte('"')
} else {
sb.WriteString(fmt.Sprintf("%v", p.DefaultValue()))
}
}
}
}
if info.maxArgs < 0 {
sb.WriteString(" ...")
}
sb.WriteString("):")
if len(info.returnType) > 0 {
sb.WriteString(info.returnType)
} else {
sb.WriteString(kern.TypeAny)
}
sb.WriteString("{}")
return sb.String()
}
func (info *funcInfo) Name() string {
return info.name
}
func (info *funcInfo) MinArgs() int {
return info.minArgs
}
func (info *funcInfo) MaxArgs() int {
return info.maxArgs
}
func (info *funcInfo) Functor() kern.Functor {
return info.functor
}
func (info *funcInfo) AllocContext(parentCtx kern.ExprContext) (ctx kern.ExprContext) {
if defCtx := info.functor.GetDefinitionContext(); defCtx != nil {
ctx = defCtx.Clone()
ctx.SetParent(defCtx)
} else {
ctx = parentCtx.Clone()
ctx.SetParent(parentCtx)
}
return
}
func (info *funcInfo) ParamSpec(paramName string) kern.ExprFuncParam {
for _, spec := range info.formalParams {
if spec.Name() == paramName {
return spec
}
}
return nil
}
func initActualParams(ctx kern.ExprContext, info kern.ExprFunc, callTerm *scan.Term) (actualParams map[string]any, err error) {
var varArgs []any
var varName string
namedParamsStarted := false
formalParams := info.Params()
actualParams = make(map[string]any, len(formalParams))
if callTerm == nil {
return
}
for i, tree := range callTerm.Children {
var paramValue any
paramCtx := ctx.Clone()
if paramValue, err = tree.Compute(paramCtx); err != nil {
break
}
if paramName, namedParam := kern.GetAssignVarName(tree); namedParam {
if info.ParamSpec(paramName) == nil {
err = fmt.Errorf("%s(): unknown param %q", info.Name(), paramName)
break
}
actualParams[paramName] = paramValue
namedParamsStarted = true
} else if !namedParamsStarted {
if varArgs != nil {
varArgs = append(varArgs, paramValue)
} else if i < len(formalParams) {
spec := formalParams[i]
if spec.IsRepeat() {
varArgs = make([]any, 0, len(callTerm.Children)-i)
varArgs = append(varArgs, paramValue)
varName = spec.Name()
} else {
actualParams[spec.Name()] = paramValue
}
} else {
err = kern.ErrTooManyParams(info.Name(), len(formalParams), len(callTerm.Children))
break
}
} else {
err = fmt.Errorf("%s(): positional param nr %d not allowed after named params", info.Name(), i+1)
break
}
}
if err == nil {
if varArgs != nil {
actualParams[varName] = varArgs
}
}
return
}
func (info *funcInfo) PrepareCall(name string, actualParams map[string]any) (err error) {
passedCount := len(actualParams)
if info.MinArgs() > passedCount {
err = kern.ErrTooFewParams(name, info.MinArgs(), info.MaxArgs(), passedCount)
return
}
if passedCount < len(info.formalParams) {
for _, p := range info.formalParams {
if _, exists := actualParams[p.Name()]; !exists {
if !p.IsDefault() {
break
}
if p.IsRepeat() {
varArgs := make([]any, 1)
varArgs[0] = p.DefaultValue()
actualParams[p.Name()] = varArgs
} else {
actualParams[p.Name()] = p.DefaultValue()
}
}
}
}
if info.MaxArgs() >= 0 && info.MaxArgs() < len(actualParams) {
err = kern.ErrTooManyParams(name, info.MaxArgs(), len(actualParams))
}
return
}
// ----- Call a function ---
// func getAssignVarName(t *term) (name string, ok bool) {
// if ok = t.symbol() == SymEqual; ok {
// name = t.children[0].source()
// }
// return
// }
// func CallFunctionByTerm(parentCtx expr.ExprContext, name string, callTerm *term) (result any, err error) {
// var actualParams map[string]any
// if info, exists := GetFuncInfo(parentCtx, name); exists {
// if actualParams, err = initActualParams(parentCtx, info, callTerm); err == nil {
// ctx := info.AllocContext(parentCtx)
// if err = info.PrepareCall(name, actualParams); err == nil {
// functor := info.Functor()
// result, err = functor.InvokeNamed(ctx, name, actualParams)
// exportObjectsToParent(ctx)
// }
// }
// } else {
// err = fmt.Errorf("unknown function %s()", name)
// }
// return
// }
// func CallFunctionByArgs(parentCtx expr.ExprContext, name string, args []any) (result any, err error) {
// var actualParams map[string]any
// if info, exists := GetFuncInfo(parentCtx, name); exists {
// functor := info.Functor()
// actualParams = bindActualParams(functor, args)
// ctx := info.AllocContext(parentCtx)
// if err = info.PrepareCall(name, actualParams); err == nil {
// result, err = functor.InvokeNamed(ctx, name, actualParams)
// exportObjectsToParent(ctx)
// }
// } else {
// err = fmt.Errorf("unknown function %s()", name)
// }
// return
// }
// func CallFunctionByParams(parentCtx expr.ExprContext, name string, actualParams map[string]any) (result any, err error) {
// //var actualParams map[string]any
// if info, exists := GetFuncInfo(parentCtx, name); exists {
// functor := info.Functor()
// ctx := info.AllocContext(parentCtx)
// if err = info.PrepareCall(name, actualParams); err == nil {
// result, err = functor.InvokeNamed(ctx, name, actualParams)
// exportObjectsToParent(ctx)
// }
// } else {
// err = fmt.Errorf("unknown function %s()", name)
// }
// return
// }
// func GetParam(args map[string]any, paramName string, paramNum int) (value any, exists bool) {
// if value, exists = args[paramName]; !exists {
// if paramNum > 0 && paramNum <= len(args) {
// value, exists = args["arg"+strconv.Itoa(paramNum)]
// }
// }
// return
// }
// func bindActualParams(functor Functor, args []any) (actualParams map[string]any) {
// formalParams := functor.GetParams()
// actualParams = make(map[string]any, len(args))
// for i, arg := range args {
// if i < len(formalParams) {
// actualParams[formalParams[i].Name()] = arg
// } else {
// actualParams["arg"+strconv.Itoa(i+1)] = arg
// }
// }
// return
// }
+1 -1
View File
@@ -45,7 +45,7 @@ func EvalStringV(source string, args []Arg) (result any, err error) {
functor := kern.NewGolangFunctor(f) functor := kern.NewGolangFunctor(f)
// ctx.RegisterFunc(arg.Name, functor, 0, -1) // ctx.RegisterFunc(arg.Name, functor, 0, -1)
ctx.RegisterFunc(arg.Name, functor, kern.TypeAny, []kern.ExprFuncParam{ ctx.RegisterFunc(arg.Name, functor, kern.TypeAny, []kern.ExprFuncParam{
NewFuncParamFlagDef(kern.ParamValue, PfDefault|PfRepeat, 0), kern.NewFuncParamFlagDef(kern.ParamValue, kern.PfDefault|kern.PfRepeat, 0),
}) })
} else { } else {
err = fmt.Errorf("invalid function specification: %q", arg.Name) err = fmt.Errorf("invalid function specification: %q", arg.Name)
+20 -2
View File
@@ -5,10 +5,13 @@
package expr package expr
import ( import (
"fmt"
"slices"
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
) )
func NewIterator(value any) (it kern.Iterator, err error) { func NewIterator(ctx kern.ExprContext, value any, args map[string]any) (it kern.Iterator, err error) {
if value == nil { if value == nil {
return NewArrayIterator([]any{}), nil return NewArrayIterator([]any{}), nil
} }
@@ -21,9 +24,24 @@ func NewIterator(value any) (it kern.Iterator, err error) {
case []any: case []any:
it = NewArrayIterator(v) it = NewArrayIterator(v)
case kern.Iterator: case kern.Iterator:
it = v // it = v
var op kern.Functor
if len(args) >= 1 {
if opArg, ok := args["op"]; ok {
if op, ok = opArg.(kern.Functor); !ok {
err = fmt.Errorf("the 'op' argument must be a kern.Functor, got %T", opArg)
}
}
}
if err == nil {
it, err = NewIterIter(v, ctx, op, args)
}
default: default:
it = NewArrayIterator([]any{value}) it = NewArrayIterator([]any{value})
} }
return return
} }
func HasStandardOperation(name string) bool {
return slices.Contains([]string{kern.NextName, kern.ResetName, kern.IndexName, kern.CountName, kern.CurrentName, kern.CleanName}, name)
}
+132
View File
@@ -0,0 +1,132 @@
// Copyright (c) 2024-2026 Celestino Amoroso (celestino.amoroso@gmail.com).
// All rights reserved.
// iter-iter.go
package expr
import (
"fmt"
"io"
"git.portale-stac.it/go-pkg/expr/kern"
)
type IterIter struct {
it kern.Iterator
count int64
index int64
ctx kern.ExprContext
op kern.Functor
opName string
args map[string]any
current any
}
func NewIterIter(it kern.Iterator, ctx kern.ExprContext, op kern.Functor, args map[string]any) (iter kern.Iterator, err error) {
var opName string
if op != nil {
if f := op.GetFunc(); f != nil {
opName = f.Name()
// } else {
// return nil, fmt.Errorf("invalid functor argument for iter-iter: expected kern.Functor, got %T", args["op"])
}
}
if len(opName) == 0 {
opName = "anonymous"
}
iter = &IterIter{it: it, count: 0, index: -1, ctx: ctx, op: op, opName: opName, args: args}
return
}
func (it *IterIter) String() string {
return fmt.Sprintf("$(%s)", it.it)
}
func (it *IterIter) TypeName() string {
return "IterIter"
}
func (it *IterIter) HasOperation(name string) bool {
return HasStandardOperation(name)
}
func (it *IterIter) CallOperation(name string, args map[string]any) (v any, err error) {
switch name {
case kern.NextName:
v, err = it.Next()
case kern.ResetName:
err = it.Reset()
case kern.CleanName:
err = it.Clean()
case kern.IndexName:
v = int64(it.Index())
case kern.CurrentName:
v, err = it.Current()
case kern.CountName:
v = it.count
default:
err = kern.ErrNoOperation(name)
}
return
}
func (it *IterIter) Current() (item any, err error) {
if it.current != nil {
item = it.current
} else if it.op != nil {
if item, err = it.op.InvokeNamed(it.ctx, it.opName, it.args); err == nil {
it.current = item
}
} else {
var exists bool
if it.current, exists = it.ctx.GetVar("_"); !exists {
err = fmt.Errorf("current item not available")
} else {
item = it.current
}
}
return
}
func (it *IterIter) Next() (item any, err error) {
var src any
it.current = nil
ctx := it.ctx
for src, err = it.it.Next(); src == nil && err == nil; src, err = it.it.Next() {
}
if err == nil {
if src == nil {
err = io.EOF
} else {
ctx.UnsafeSetVar("_", src)
ctx.UnsafeSetVar("__", it.it.Index())
ctx.UnsafeSetVar("_#", it.it.Count())
item, err = it.Current()
ctx.DeleteVar("_#")
ctx.DeleteVar("__")
ctx.DeleteVar("_")
}
}
return
}
func (it *IterIter) Index() int64 {
return it.index
}
func (it *IterIter) Count() int64 {
return it.count
}
func (it *IterIter) Reset() error {
it.index = -1
it.count = 0
return nil
}
func (it *IterIter) Clean() error {
return nil
}
+5 -5
View File
@@ -5,19 +5,19 @@
package kern package kern
// ---- Linking with Go functions // ---- Linking with Go functions
type golangFunctor struct { type GolangFunctor struct {
BaseFunctor BaseFunctor
f FuncTemplate f FuncTemplate
} }
func NewGolangFunctor(f FuncTemplate) *golangFunctor { func NewGolangFunctor(f FuncTemplate) *GolangFunctor {
return &golangFunctor{f: f} return &GolangFunctor{f: f}
} }
func (functor *golangFunctor) TypeName() string { func (functor *GolangFunctor) TypeName() string {
return "GoFunctor" return "GoFunctor"
} }
func (functor *golangFunctor) InvokeNamed(ctx ExprContext, name string, args map[string]any) (result any, err error) { func (functor *GolangFunctor) InvokeNamed(ctx ExprContext, name string, args map[string]any) (result any, err error) {
return functor.f(ctx, name, args) return functor.f(ctx, name, args)
} }
+5
View File
@@ -37,3 +37,8 @@ type ExprFunc interface {
PrepareCall(name string, actualParams map[string]any) (err error) PrepareCall(name string, actualParams map[string]any) (err error)
AllocContext(parentCtx ExprContext) (ctx ExprContext) AllocContext(parentCtx ExprContext) (ctx ExprContext)
} }
func IsFunctor(v any) (ok bool) {
_, ok = v.(Functor)
return
}
+164
View File
@@ -0,0 +1,164 @@
// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
// All rights reserved.
// func-info.go
package kern
import (
"fmt"
"strings"
)
// --- Functions
// FuncInfo implements expr.ExprFunc
type FuncInfo struct {
name string
minArgs int
maxArgs int
functor Functor
formalParams []ExprFuncParam
returnType string
}
func NewFuncInfo(name string, functor Functor, returnType string, params []ExprFuncParam) (info *FuncInfo, err error) {
var minArgs = 0
var maxArgs = 0
for _, p := range params {
if maxArgs == -1 {
return nil, fmt.Errorf("no more params can be specified after the ellipsis symbol: %q", p.Name())
}
if p.IsDefault() || p.IsOptional() {
maxArgs++
} else if maxArgs == minArgs {
minArgs++
maxArgs++
} else {
return nil, fmt.Errorf("can't specify non-optional param after optional ones: %q", p.Name())
}
if p.IsRepeat() {
minArgs--
maxArgs = -1
}
}
info = &FuncInfo{
name: name, minArgs: minArgs, maxArgs: maxArgs, functor: functor, returnType: returnType, formalParams: params,
}
functor.SetFunc(info)
return info, nil
}
func (info *FuncInfo) Params() []ExprFuncParam {
return info.formalParams
}
func (info *FuncInfo) ReturnType() string {
return info.returnType
}
func (info *FuncInfo) ToString(opt FmtOpt) string {
var sb strings.Builder
if len(info.Name()) == 0 {
sb.WriteString("func")
} else {
sb.WriteString(info.Name())
}
sb.WriteByte('(')
if info.formalParams != nil {
for i, p := range info.formalParams {
if i > 0 {
sb.WriteString(", ")
}
sb.WriteString(p.Name())
if p.IsDefault() {
sb.WriteByte('=')
if s, ok := p.DefaultValue().(string); ok {
sb.WriteByte('"')
sb.WriteString(s)
sb.WriteByte('"')
} else {
sb.WriteString(fmt.Sprintf("%v", p.DefaultValue()))
}
}
}
}
if info.maxArgs < 0 {
sb.WriteString(" ...")
}
sb.WriteString("):")
if len(info.returnType) > 0 {
sb.WriteString(info.returnType)
} else {
sb.WriteString(TypeAny)
}
sb.WriteString("{}")
return sb.String()
}
func (info *FuncInfo) Name() string {
return info.name
}
func (info *FuncInfo) MinArgs() int {
return info.minArgs
}
func (info *FuncInfo) MaxArgs() int {
return info.maxArgs
}
func (info *FuncInfo) Functor() Functor {
return info.functor
}
func (info *FuncInfo) AllocContext(parentCtx ExprContext) (ctx ExprContext) {
if defCtx := info.functor.GetDefinitionContext(); defCtx != nil {
ctx = defCtx.Clone()
ctx.SetParent(defCtx)
} else {
ctx = parentCtx.Clone()
ctx.SetParent(parentCtx)
}
return
}
func (info *FuncInfo) ParamSpec(paramName string) ExprFuncParam {
for _, spec := range info.formalParams {
if spec.Name() == paramName {
return spec
}
}
return nil
}
func (info *FuncInfo) PrepareCall(name string, actualParams map[string]any) (err error) {
passedCount := len(actualParams)
if info.MinArgs() > passedCount {
err = ErrTooFewParams(name, info.MinArgs(), info.MaxArgs(), passedCount)
return
}
if passedCount < len(info.formalParams) {
for _, p := range info.formalParams {
if _, exists := actualParams[p.Name()]; !exists {
if !p.IsDefault() {
break
}
if p.IsRepeat() {
varArgs := make([]any, 1)
varArgs[0] = p.DefaultValue()
actualParams[p.Name()] = varArgs
} else {
actualParams[p.Name()] = p.DefaultValue()
}
}
}
}
if info.MaxArgs() >= 0 && info.MaxArgs() < len(actualParams) {
err = ErrTooManyParams(name, info.MaxArgs(), len(actualParams))
}
return
}
+5 -10
View File
@@ -14,11 +14,6 @@ type FuncTemplate func(ctx ExprContext, name string, args map[string]any) (resul
type DeepFuncTemplate func(a, b any) (eq bool, err error) type DeepFuncTemplate func(a, b any) (eq bool, err error)
func IsFunctor(v any) (ok bool) {
_, ok = v.(Functor)
return
}
// ---- Common functor definition // ---- Common functor definition
type BaseFunctor struct { type BaseFunctor struct {
info ExprFunc info ExprFunc
@@ -54,17 +49,17 @@ func (functor *BaseFunctor) GetDefinitionContext() ExprContext {
} }
// ---- Function Parameters // ---- Function Parameters
type paramFlags uint16 type FuncParamFlags uint16
const ( const (
PfDefault paramFlags = 1 << iota PfDefault FuncParamFlags = 1 << iota
PfOptional PfOptional
PfRepeat PfRepeat
) )
type funcParamInfo struct { type funcParamInfo struct {
name string name string
flags paramFlags flags FuncParamFlags
defaultValue any defaultValue any
} }
@@ -72,11 +67,11 @@ func NewFuncParam(name string) ExprFuncParam {
return &funcParamInfo{name: name} return &funcParamInfo{name: name}
} }
func NewFuncParamFlag(name string, flags paramFlags) ExprFuncParam { func NewFuncParamFlag(name string, flags FuncParamFlags) ExprFuncParam {
return &funcParamInfo{name: name, flags: flags} return &funcParamInfo{name: name, flags: flags}
} }
func NewFuncParamFlagDef(name string, flags paramFlags, defValue any) *funcParamInfo { func NewFuncParamFlagDef(name string, flags FuncParamFlags, defValue any) *funcParamInfo {
return &funcParamInfo{name: name, flags: flags, defaultValue: defValue} return &funcParamInfo{name: name, flags: flags, defaultValue: defValue}
} }
+3 -3
View File
@@ -70,14 +70,14 @@ func evalFuncDef(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
paramList := make([]kern.ExprFuncParam, 0, len(opTerm.Children)) paramList := make([]kern.ExprFuncParam, 0, len(opTerm.Children))
for _, param := range opTerm.Children { for _, param := range opTerm.Children {
var defValue any var defValue any
flags := paramFlags(0) flags := kern.FuncParamFlags(0)
if len(param.Children) > 0 { if len(param.Children) > 0 {
flags |= PfDefault flags |= kern.PfDefault
if defValue, err = param.Children[0].Compute(ctx); err != nil { if defValue, err = param.Children[0].Compute(ctx); err != nil {
return return
} }
} }
info := NewFuncParamFlagDef(param.Source(), flags, defValue) info := kern.NewFuncParamFlagDef(param.Source(), flags, defValue)
paramList = append(paramList, info) paramList = append(paramList, info)
} }
v = newExprFunctor(ast, paramList, ctx) v = newExprFunctor(ast, paramList, ctx)
+55 -7
View File
@@ -5,7 +5,9 @@
package expr package expr
import ( import (
"fmt"
"slices" "slices"
"strconv"
"strings" "strings"
"git.portale-stac.it/go-pkg/expr/kern" "git.portale-stac.it/go-pkg/expr/kern"
@@ -125,7 +127,7 @@ func evalIterator(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
} else { } else {
if dictIt, ok := firstChildValue.(*kern.DictType); ok { if dictIt, ok := firstChildValue.(*kern.DictType); ok {
var args []any var args []any
if args, err = evalSibling(ctx, opTerm.Children, nil); err == nil { if args, err = evalSiblings(ctx, opTerm.Children, nil); err == nil {
v, err = NewDictIterator(dictIt, args) v, err = NewDictIterator(dictIt, args)
} }
} else { } else {
@@ -134,24 +136,70 @@ func evalIterator(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
} }
} else if list, ok := firstChildValue.(*kern.ListType); ok { } else if list, ok := firstChildValue.(*kern.ListType); ok {
var args []any var args []any
if args, err = evalSibling(ctx, opTerm.Children, nil); err == nil { if args, err = evalSiblings(ctx, opTerm.Children, nil); err == nil {
v = NewListIterator(list, args) v = NewListIterator(list, args)
} }
} else if intVal, ok := firstChildValue.(int64); ok { } else if intVal, ok := firstChildValue.(int64); ok {
var args []any var args []any
if args, err = evalSibling(ctx, opTerm.Children, intVal); err == nil { if args, err = evalSiblings(ctx, opTerm.Children, intVal); err == nil {
v, err = NewIntIterator(args) v, err = NewIntIterator(args)
} }
} else { } else {
var list []any var siblings []any
if list, err = evalSibling(ctx, opTerm.Children, firstChildValue); err == nil { if siblings, err = evalSiblings(ctx, opTerm.Children, firstChildValue); err == nil {
v = NewArrayIterator(list) // if v, err = evalIterIter(ctx, firstChildValue, siblings); err == nil && v == nil {
// if it, ok := firstChildValue.(kern.Iterator); ok {
// if len(siblings) > 1 {
// if op, ok := siblings[1].(kern.Functor); ok {
// args := make(map[string]any, len(siblings)-2)
// for i, arg := range siblings[2:] {
// args["arg"+strconv.Itoa(i+1)] = arg
// }
// v, err = NewIterIter(it, ctx, op, args)
// } else {
// err = opTerm.Children[1].Errorf("the first sibling parameter must be a functor to be used as operation for the iterator")
// }
// } else {
// v, err = NewIterIter(it, ctx, nil, nil)
// }
if v, err = evalIterIter(ctx, firstChildValue, siblings); err == nil && v == nil {
v = NewArrayIterator(siblings)
}
} }
} }
return return
} }
func evalSibling(ctx kern.ExprContext, terms []*scan.Term, firstChildValue any) (list []any, err error) { func evalIterIter(ctx kern.ExprContext, firstChildValue any, siblings []any) (v any, err error) {
var op kern.Functor
var args map[string]any
if it, ok := firstChildValue.(kern.Iterator); ok {
if len(siblings) > 1 {
if op, ok = siblings[1].(kern.Functor); ok {
args = make(map[string]any, len(siblings)-2)
for i, arg := range siblings[2:] {
switch a := arg.(type) {
case *kern.DictType:
for keyAny, item := range *a {
if key, ok := keyAny.(string); ok {
args[key] = item
}
}
default:
args["arg"+strconv.Itoa(i+1)] = arg
}
}
} else if op == nil {
return nil, fmt.Errorf("the first sibling parameter must be a functor to be used as operation for the iterator")
}
}
v, err = NewIterIter(it, ctx, op, args)
}
return
}
func evalSiblings(ctx kern.ExprContext, terms []*scan.Term, firstChildValue any) (list []any, err error) {
items := make([]any, 0, len(terms)) items := make([]any, 0, len(terms))
for i, tree := range terms { for i, tree := range terms {
var param any var param any
+1 -1
View File
@@ -37,7 +37,7 @@ func evalBuiltin(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
} else { } else {
var moduleSpec any var moduleSpec any
var it kern.Iterator var it kern.Iterator
if it, err = NewIterator(childValue); err != nil { if it, err = NewIterator(ctx, childValue, nil); err != nil {
return return
} }
for moduleSpec, err = it.Next(); err == nil; moduleSpec, err = it.Next() { for moduleSpec, err = it.Next(); err == nil; moduleSpec, err = it.Next() {
+1 -1
View File
@@ -111,7 +111,7 @@ func evalAssignDefault(ctx kern.ExprContext, opTerm *scan.Term) (v any, err erro
if functor, ok := rightValue.(kern.Functor); ok { if functor, ok := rightValue.(kern.Functor); ok {
//ctx.RegisterFunc(leftTerm.source(), functor, 0, -1) //ctx.RegisterFunc(leftTerm.source(), functor, 0, -1)
ctx.RegisterFunc(leftTerm.Source(), functor, kern.TypeAny, []kern.ExprFuncParam{ ctx.RegisterFunc(leftTerm.Source(), functor, kern.TypeAny, []kern.ExprFuncParam{
NewFuncParamFlag(kern.ParamValue, PfDefault|PfRepeat), kern.NewFuncParamFlag(kern.ParamValue, kern.PfDefault|kern.PfRepeat),
}) })
} else { } else {
v = rightValue v = rightValue
+1 -1
View File
@@ -37,7 +37,7 @@ func evalDigest(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
return return
} }
if it, err = NewIterator(leftValue); err != nil { if it, err = NewIterator(ctx, leftValue, nil); err != nil {
return nil, fmt.Errorf("left operand of DIGEST must be an iterable data-source; got %s", kern.TypeName(leftValue)) return nil, fmt.Errorf("left operand of DIGEST must be an iterable data-source; got %s", kern.TypeName(leftValue))
} }
+5 -2
View File
@@ -28,6 +28,7 @@ func evalFilter(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
var leftValue, rightValue any var leftValue, rightValue any
var it kern.Iterator var it kern.Iterator
var item any var item any
var ok bool
if err = opTerm.CheckOperands(); err != nil { if err = opTerm.CheckOperands(); err != nil {
return return
@@ -37,8 +38,10 @@ func evalFilter(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
return return
} }
if it, err = NewIterator(leftValue); err != nil { if it, ok = leftValue.(kern.Iterator); !ok {
return nil, fmt.Errorf("left operand of FILTER must be an iterable data-source; got %s", kern.TypeName(leftValue)) if it, err = NewIterator(ctx, leftValue, nil); err != nil {
return nil, fmt.Errorf("left operand of FILTER must be an iterable data-source; got %s", kern.TypeName(leftValue))
}
} }
values := kern.NewListA() values := kern.NewListA()
+1 -1
View File
@@ -40,7 +40,7 @@ func evalGroupBy(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
return return
} }
if it, err = NewIterator(leftValue); err != nil { if it, err = NewIterator(ctx, leftValue, nil); err != nil {
return nil, fmt.Errorf("left operand of MAP must be an iterable data-source; got %s", kern.TypeName(leftValue)) return nil, fmt.Errorf("left operand of MAP must be an iterable data-source; got %s", kern.TypeName(leftValue))
} }
+2 -2
View File
@@ -41,11 +41,11 @@ func evalJoin(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
return return
} }
if itLeft, err = NewIterator(leftValue); err != nil { if itLeft, err = NewIterator(ctx, leftValue, nil); err != nil {
return nil, fmt.Errorf("left operand of JOIN must be an iterable data-source; got %s", kern.TypeName(leftValue)) return nil, fmt.Errorf("left operand of JOIN must be an iterable data-source; got %s", kern.TypeName(leftValue))
} }
if itRight, err = NewIterator(rightValue); err != nil { if itRight, err = NewIterator(ctx, rightValue, nil); err != nil {
return nil, fmt.Errorf("right operand of JOIN must be an iterable data-source; got %s", kern.TypeName(rightValue)) return nil, fmt.Errorf("right operand of JOIN must be an iterable data-source; got %s", kern.TypeName(rightValue))
} }
+1 -1
View File
@@ -37,7 +37,7 @@ func evalMap(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
return return
} }
if it, err = NewIterator(leftValue); err != nil { if it, err = NewIterator(ctx, leftValue, nil); err != nil {
return nil, fmt.Errorf("left operand of MAP must be an iterable data-source; got %s", kern.TypeName(leftValue)) return nil, fmt.Errorf("left operand of MAP must be an iterable data-source; got %s", kern.TypeName(leftValue))
} }
+1 -1
View File
@@ -100,7 +100,7 @@ func importPluginFromSearchPath(ctx kern.ExprContext, name any) (count int, err
var it kern.Iterator var it kern.Iterator
dirList := buildSearchDirList(ctx, "plugin", ENV_EXPR_PLUGIN_PATH) dirList := buildSearchDirList(ctx, "plugin", ENV_EXPR_PLUGIN_PATH)
count = 0 count = 0
if it, err = NewIterator(name); err != nil { if it, err = NewIterator(ctx, name, nil); err != nil {
return return
} }
for moduleSpec, err = it.Next(); err == nil; moduleSpec, err = it.Next() { for moduleSpec, err = it.Next(); err == nil; moduleSpec, err = it.Next() {
+3 -3
View File
@@ -200,12 +200,12 @@ func (ctx *SimpleStore) GetLocalFuncInfo(name string) (info kern.ExprFunc, exist
} }
func (ctx *SimpleStore) RegisterFuncInfo(info kern.ExprFunc) { func (ctx *SimpleStore) RegisterFuncInfo(info kern.ExprFunc) {
ctx.funcStore[info.Name()], _ = info.(*funcInfo) ctx.funcStore[info.Name()], _ = info.(*kern.FuncInfo)
} }
func (ctx *SimpleStore) RegisterFunc(name string, functor kern.Functor, returnType string, params []kern.ExprFuncParam) (exprFunc kern.ExprFunc, err error) { func (ctx *SimpleStore) RegisterFunc(name string, functor kern.Functor, returnType string, params []kern.ExprFuncParam) (exprFunc kern.ExprFunc, err error) {
var info *funcInfo var info *kern.FuncInfo
if info, err = newFuncInfo(name, functor, returnType, params); err == nil { if info, err = kern.NewFuncInfo(name, functor, returnType, params); err == nil {
ctx.funcStore[name] = info ctx.funcStore[name] = info
exprFunc = info exprFunc = info
} }
+1 -1
View File
@@ -100,7 +100,7 @@ func TestGoFunction(t *testing.T) {
ctx := NewSimpleStoreWithoutGlobalContext() ctx := NewSimpleStoreWithoutGlobalContext()
ctx.RegisterFunc("myName", kern.NewGolangFunctor(myName), kern.TypeString, []kern.ExprFuncParam{ ctx.RegisterFunc("myName", kern.NewGolangFunctor(myName), kern.TypeString, []kern.ExprFuncParam{
NewFuncParamFlagDef("name", PfOptional|PfDefault, "Celestino Amoroso"), kern.NewFuncParamFlagDef("name", kern.PfOptional|kern.PfDefault, "Celestino Amoroso"),
}) })
runCtxTestSuite(t, ctx, section, inputs) runCtxTestSuite(t, ctx, section, inputs)
+63
View File
@@ -0,0 +1,63 @@
// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
// All rights reserved.
// t_iter-iter_test.go
package expr
import (
"testing"
"git.portale-stac.it/go-pkg/expr/kern"
)
func TestIterIterator(t *testing.T) {
section := "Iterator"
inputs := []inputType{
/* 1 */ {`it=$(4); $(it) filter ${_}==100`, kern.NewListA(), nil},
/* 2 */ {`it=$(4); $(it, func(){$_}) filter ${_}==100`, kern.NewListA(), nil},
/* 3 */ {`it=$(4); $(it, func(arg1){arg1+$_}, 10) filter ${_}==100`, kern.NewListA(), nil},
}
runTestSuiteSpec(t, section, inputs, 3)
// runTestSuite(t, section, inputs)
}
// func TestNewIterIterator(t *testing.T) {
// var it kern.Iterator
// var err error
// list := kern.NewListA("a", "b", "c", "d")
// itList := NewListIterator(list, []any{1, 3, 1})
// it, err = NewIterator(nil, itList, map[string]any{"op": kern.NewFunctor("test")})
// if err != nil {
// t.Errorf("error: %v", err)
// } else {
// if item, err := it.Next(); err != nil {
// t.Errorf("error: %v", err)
// } else if item != "b" {
// t.Errorf("expected %q, got %q", "b", item)
// } else {
// t.Logf("Next: %v", item)
// }
// }
// }
// func TestNewIterIteratorNoOp(t *testing.T) {
// var it kern.Iterator
// var err error
// list := kern.NewListA("a", "b", "c", "d")
// itList := NewListIterator(list, []any{1, 3, 1})
// it, err = NewIterator(nil, itList, nil)
// if err != nil {
// t.Errorf("error: %v", err)
// } else {
// if item, err := it.Next(); err != nil {
// t.Errorf("error: %v", err)
// } else if item != "b" {
// t.Errorf("expected %q, got %q", "b", item)
// } else {
// t.Logf("Next: %v", item)
// }
// }
// }
+6 -6
View File
@@ -61,7 +61,7 @@ func TestNewIterList2(t *testing.T) {
func TestNewIterList3(t *testing.T) { func TestNewIterList3(t *testing.T) {
list := []any{"a", "b", "c", "d"} list := []any{"a", "b", "c", "d"}
it, _ := NewIterator(list) it, _ := NewIterator(nil, list, nil)
if item, err := it.Next(); err != nil { if item, err := it.Next(); err != nil {
t.Errorf("error: %v", err) t.Errorf("error: %v", err)
} else if item != "a" { } else if item != "a" {
@@ -73,7 +73,7 @@ func TestNewIterList3(t *testing.T) {
func TestNewIterList4(t *testing.T) { func TestNewIterList4(t *testing.T) {
list := any(nil) list := any(nil)
it, _ := NewIterator(list) it, _ := NewIterator(nil, list, nil)
if _, err := it.Next(); err != io.EOF { if _, err := it.Next(); err != io.EOF {
t.Errorf("error: %v", err) t.Errorf("error: %v", err)
} }
@@ -81,7 +81,7 @@ func TestNewIterList4(t *testing.T) {
func TestNewIterList5(t *testing.T) { func TestNewIterList5(t *testing.T) {
list := "123" list := "123"
it, _ := NewIterator(list) it, _ := NewIterator(nil, list, nil)
if item, err := it.Next(); err != nil { if item, err := it.Next(); err != nil {
t.Errorf("error: %v", err) t.Errorf("error: %v", err)
} else if item != "123" { } else if item != "123" {
@@ -93,8 +93,8 @@ func TestNewIterList5(t *testing.T) {
func TestNewIterList6(t *testing.T) { func TestNewIterList6(t *testing.T) {
list := kern.NewListA("a", "b", "c", "d") list := kern.NewListA("a", "b", "c", "d")
it1, _ := NewIterator(list) it1, _ := NewIterator(nil, list, nil)
it, _ := NewIterator(it1) it, _ := NewIterator(nil, it1, nil)
if item, err := it.Next(); err != nil { if item, err := it.Next(); err != nil {
t.Errorf("error: %v", err) t.Errorf("error: %v", err)
} else if item != "a" { } else if item != "a" {
@@ -106,7 +106,7 @@ func TestNewIterList6(t *testing.T) {
func TestNewString(t *testing.T) { func TestNewString(t *testing.T) {
list := "123" list := "123"
it, _ := NewIterator(list) it, _ := NewIterator(nil, list, nil)
if s := it.String(); s != "$([#1])" { if s := it.String(); s != "$([#1])" {
t.Errorf("expected $([#1]), got %s", s) t.Errorf("expected $([#1]), got %s", s)
} }