new iter-iter iterator and kern.func-info module
This commit is contained in:
+10
-10
@@ -272,7 +272,7 @@ func setFunc(ctx kern.ExprContext, name string, args map[string]any) (result any
|
||||
|
||||
func ImportBuiltinsFuncs(ctx kern.ExprContext) {
|
||||
anyParams := []kern.ExprFuncParam{
|
||||
NewFuncParam(kern.ParamValue),
|
||||
kern.NewFuncParam(kern.ParamValue),
|
||||
}
|
||||
|
||||
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("string", kern.NewGolangFunctor(stringFunc), kern.TypeString, anyParams)
|
||||
ctx.RegisterFunc("fract", kern.NewGolangFunctor(fractFunc), kern.TypeFraction, []kern.ExprFuncParam{
|
||||
NewFuncParam(kern.ParamValue),
|
||||
NewFuncParamFlagDef(ParamDenominator, PfDefault, int64(1)),
|
||||
kern.NewFuncParam(kern.ParamValue),
|
||||
kern.NewFuncParamFlagDef(ParamDenominator, kern.PfDefault, int64(1)),
|
||||
})
|
||||
|
||||
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{
|
||||
NewFuncParam(kern.ParamName),
|
||||
NewFuncParamFlagDef(kern.ParamValue, PfDefault, nil),
|
||||
kern.NewFuncParam(kern.ParamName),
|
||||
kern.NewFuncParamFlagDef(kern.ParamValue, kern.PfDefault, nil),
|
||||
})
|
||||
|
||||
ctx.RegisterFunc("set", kern.NewGolangFunctor(setFunc), kern.TypeAny, []kern.ExprFuncParam{
|
||||
NewFuncParam(kern.ParamName),
|
||||
NewFuncParam(kern.ParamValue),
|
||||
kern.NewFuncParam(kern.ParamName),
|
||||
kern.NewFuncParam(kern.ParamValue),
|
||||
})
|
||||
|
||||
// ctx.RegisterFunc("unset", kern.NewGolangFunctor(unsetFunc), kern.TypeAny, []kern.ExprFuncParam{
|
||||
// NewFuncParam(kern.ParamName),
|
||||
// NewFuncParam(kern.ParamValue),
|
||||
// kern.NewFuncParam(kern.ParamName),
|
||||
// kern.NewFuncParam(kern.ParamValue),
|
||||
// })
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -47,10 +47,10 @@ func printLnFunc(ctx kern.ExprContext, name string, args map[string]any) (result
|
||||
|
||||
func ImportFmtFuncs(ctx kern.ExprContext) {
|
||||
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{
|
||||
NewFuncParamFlag(kern.ParamItem, PfRepeat),
|
||||
kern.NewFuncParamFlag(kern.ParamItem, kern.PfRepeat),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -69,10 +69,10 @@ func doImport(ctx kern.ExprContext, name string, dirList []string, it kern.Itera
|
||||
|
||||
func ImportImportFuncs(ctx kern.ExprContext) {
|
||||
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{
|
||||
NewFuncParamFlag(kern.ParamFilepath, PfRepeat),
|
||||
kern.NewFuncParamFlag(kern.ParamFilepath, kern.PfRepeat),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -94,9 +94,9 @@ func runFunc(ctx kern.ExprContext, name string, args map[string]any) (result any
|
||||
|
||||
func ImportIterFuncs(ctx kern.ExprContext) {
|
||||
ctx.RegisterFunc("run", kern.NewGolangFunctor(runFunc), kern.TypeAny, []kern.ExprFuncParam{
|
||||
NewFuncParam(kern.ParamIterator),
|
||||
NewFuncParamFlag(iterParamOperator, PfOptional),
|
||||
NewFuncParamFlag(iterParamVars, PfOptional),
|
||||
kern.NewFuncParam(kern.ParamIterator),
|
||||
kern.NewFuncParamFlag(iterParamOperator, kern.PfOptional),
|
||||
kern.NewFuncParamFlag(iterParamVars, kern.PfOptional),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -172,11 +172,11 @@ func mulFunc(ctx kern.ExprContext, name string, args map[string]any) (result any
|
||||
|
||||
func ImportMathFuncs(ctx kern.ExprContext) {
|
||||
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{
|
||||
NewFuncParamFlagDef(kern.ParamValue, PfDefault|PfRepeat, int64(1)),
|
||||
kern.NewFuncParamFlagDef(kern.ParamValue, kern.PfDefault|kern.PfRepeat, int64(1)),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
+10
-10
@@ -224,37 +224,37 @@ func fileReadTextAllFunc(ctx kern.ExprContext, name string, args map[string]any)
|
||||
|
||||
func ImportOsFuncs(ctx kern.ExprContext) {
|
||||
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{
|
||||
NewFuncParam(kern.ParamFilepath),
|
||||
kern.NewFuncParam(kern.ParamFilepath),
|
||||
})
|
||||
|
||||
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{
|
||||
NewFuncParam(kern.ParamHandle),
|
||||
kern.NewFuncParam(kern.ParamHandle),
|
||||
})
|
||||
|
||||
ctx.RegisterFunc("fileWriteText", kern.NewGolangFunctor(fileWriteTextFunc), kern.TypeInt, []kern.ExprFuncParam{
|
||||
NewFuncParam(kern.ParamHandle),
|
||||
NewFuncParamFlagDef(kern.ParamItem, PfDefault|PfRepeat, ""),
|
||||
kern.NewFuncParam(kern.ParamHandle),
|
||||
kern.NewFuncParamFlagDef(kern.ParamItem, kern.PfDefault|kern.PfRepeat, ""),
|
||||
})
|
||||
|
||||
ctx.RegisterFunc("fileReadText", kern.NewGolangFunctor(fileReadTextFunc), kern.TypeString, []kern.ExprFuncParam{
|
||||
NewFuncParam(kern.ParamHandle),
|
||||
NewFuncParamFlagDef(osLimitCh, PfDefault, "\n"),
|
||||
kern.NewFuncParam(kern.ParamHandle),
|
||||
kern.NewFuncParamFlagDef(osLimitCh, kern.PfDefault, "\n"),
|
||||
})
|
||||
|
||||
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{
|
||||
NewFuncParam(paramHandleOrPath),
|
||||
kern.NewFuncParam(paramHandleOrPath),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
+17
-17
@@ -225,44 +225,44 @@ func lowerStrFunc(ctx kern.ExprContext, name string, args map[string]any) (resul
|
||||
// Import above functions in the context
|
||||
func ImportStringFuncs(ctx kern.ExprContext) {
|
||||
ctx.RegisterFunc("strJoin", kern.NewGolangFunctor(joinStrFunc), kern.TypeString, []kern.ExprFuncParam{
|
||||
NewFuncParam(kern.ParamSeparator),
|
||||
NewFuncParamFlag(kern.ParamItem, PfRepeat),
|
||||
kern.NewFuncParam(kern.ParamSeparator),
|
||||
kern.NewFuncParamFlag(kern.ParamItem, kern.PfRepeat),
|
||||
})
|
||||
|
||||
ctx.RegisterFunc("strSub", kern.NewGolangFunctor(subStrFunc), kern.TypeString, []kern.ExprFuncParam{
|
||||
NewFuncParam(kern.ParamSource),
|
||||
NewFuncParamFlagDef(kern.ParamStart, PfDefault, int64(0)),
|
||||
NewFuncParamFlagDef(kern.ParamCount, PfDefault, int64(-1)),
|
||||
kern.NewFuncParam(kern.ParamSource),
|
||||
kern.NewFuncParamFlagDef(kern.ParamStart, kern.PfDefault, int64(0)),
|
||||
kern.NewFuncParamFlagDef(kern.ParamCount, kern.PfDefault, int64(-1)),
|
||||
})
|
||||
|
||||
ctx.RegisterFunc("strSplit", kern.NewGolangFunctor(splitStrFunc), "list of "+kern.TypeString, []kern.ExprFuncParam{
|
||||
NewFuncParam(kern.ParamSource),
|
||||
NewFuncParamFlagDef(kern.ParamSeparator, PfDefault, ""),
|
||||
NewFuncParamFlagDef(kern.ParamCount, PfDefault, int64(-1)),
|
||||
kern.NewFuncParam(kern.ParamSource),
|
||||
kern.NewFuncParamFlagDef(kern.ParamSeparator, kern.PfDefault, ""),
|
||||
kern.NewFuncParamFlagDef(kern.ParamCount, kern.PfDefault, int64(-1)),
|
||||
})
|
||||
|
||||
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{
|
||||
NewFuncParam(kern.ParamSource),
|
||||
NewFuncParam(kern.ParamPrefix),
|
||||
NewFuncParamFlag(strParamOther, PfRepeat),
|
||||
kern.NewFuncParam(kern.ParamSource),
|
||||
kern.NewFuncParam(kern.ParamPrefix),
|
||||
kern.NewFuncParamFlag(strParamOther, kern.PfRepeat),
|
||||
})
|
||||
|
||||
ctx.RegisterFunc("strEndsWith", kern.NewGolangFunctor(endsWithStrFunc), kern.TypeBoolean, []kern.ExprFuncParam{
|
||||
NewFuncParam(kern.ParamSource),
|
||||
NewFuncParam(kern.ParamSuffix),
|
||||
NewFuncParamFlag(strParamOther, PfRepeat),
|
||||
kern.NewFuncParam(kern.ParamSource),
|
||||
kern.NewFuncParam(kern.ParamSuffix),
|
||||
kern.NewFuncParamFlag(strParamOther, kern.PfRepeat),
|
||||
})
|
||||
|
||||
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{
|
||||
NewFuncParam(kern.ParamSource),
|
||||
kern.NewFuncParam(kern.ParamSource),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
+5
-3
@@ -116,8 +116,11 @@ func NewDictIterator(dict *kern.DictType, args []any) (it *DictIterator, err err
|
||||
}
|
||||
}
|
||||
|
||||
dictIt.makeKeys(*dict, sortType)
|
||||
return dictIt, err
|
||||
if err == nil {
|
||||
dictIt.makeKeys(*dict, sortType)
|
||||
it = dictIt
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func NewMapIterator(m map[any]any) (it *DictIterator) {
|
||||
@@ -139,7 +142,6 @@ func (it *DictIterator) TypeName() string {
|
||||
}
|
||||
|
||||
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)
|
||||
return yes
|
||||
}
|
||||
|
||||
-388
@@ -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
@@ -45,7 +45,7 @@ func EvalStringV(source string, args []Arg) (result any, err error) {
|
||||
functor := kern.NewGolangFunctor(f)
|
||||
// ctx.RegisterFunc(arg.Name, functor, 0, -1)
|
||||
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 {
|
||||
err = fmt.Errorf("invalid function specification: %q", arg.Name)
|
||||
|
||||
+20
-2
@@ -5,10 +5,13 @@
|
||||
package expr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"slices"
|
||||
|
||||
"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 {
|
||||
return NewArrayIterator([]any{}), nil
|
||||
}
|
||||
@@ -21,9 +24,24 @@ func NewIterator(value any) (it kern.Iterator, err error) {
|
||||
case []any:
|
||||
it = NewArrayIterator(v)
|
||||
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:
|
||||
it = NewArrayIterator([]any{value})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func HasStandardOperation(name string) bool {
|
||||
return slices.Contains([]string{kern.NextName, kern.ResetName, kern.IndexName, kern.CountName, kern.CurrentName, kern.CleanName}, name)
|
||||
}
|
||||
|
||||
+132
@@ -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,19 +5,19 @@
|
||||
package kern
|
||||
|
||||
// ---- Linking with Go functions
|
||||
type golangFunctor struct {
|
||||
type GolangFunctor struct {
|
||||
BaseFunctor
|
||||
f FuncTemplate
|
||||
}
|
||||
|
||||
func NewGolangFunctor(f FuncTemplate) *golangFunctor {
|
||||
return &golangFunctor{f: f}
|
||||
func NewGolangFunctor(f FuncTemplate) *GolangFunctor {
|
||||
return &GolangFunctor{f: f}
|
||||
}
|
||||
|
||||
func (functor *golangFunctor) TypeName() string {
|
||||
func (functor *GolangFunctor) TypeName() string {
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -37,3 +37,8 @@ type ExprFunc interface {
|
||||
PrepareCall(name string, actualParams map[string]any) (err error)
|
||||
AllocContext(parentCtx ExprContext) (ctx ExprContext)
|
||||
}
|
||||
|
||||
func IsFunctor(v any) (ok bool) {
|
||||
_, ok = v.(Functor)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
func IsFunctor(v any) (ok bool) {
|
||||
_, ok = v.(Functor)
|
||||
return
|
||||
}
|
||||
|
||||
// ---- Common functor definition
|
||||
type BaseFunctor struct {
|
||||
info ExprFunc
|
||||
@@ -54,17 +49,17 @@ func (functor *BaseFunctor) GetDefinitionContext() ExprContext {
|
||||
}
|
||||
|
||||
// ---- Function Parameters
|
||||
type paramFlags uint16
|
||||
type FuncParamFlags uint16
|
||||
|
||||
const (
|
||||
PfDefault paramFlags = 1 << iota
|
||||
PfDefault FuncParamFlags = 1 << iota
|
||||
PfOptional
|
||||
PfRepeat
|
||||
)
|
||||
|
||||
type funcParamInfo struct {
|
||||
name string
|
||||
flags paramFlags
|
||||
flags FuncParamFlags
|
||||
defaultValue any
|
||||
}
|
||||
|
||||
@@ -72,11 +67,11 @@ func NewFuncParam(name string) ExprFuncParam {
|
||||
return &funcParamInfo{name: name}
|
||||
}
|
||||
|
||||
func NewFuncParamFlag(name string, flags paramFlags) ExprFuncParam {
|
||||
func NewFuncParamFlag(name string, flags FuncParamFlags) ExprFuncParam {
|
||||
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}
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -70,14 +70,14 @@ func evalFuncDef(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
||||
paramList := make([]kern.ExprFuncParam, 0, len(opTerm.Children))
|
||||
for _, param := range opTerm.Children {
|
||||
var defValue any
|
||||
flags := paramFlags(0)
|
||||
flags := kern.FuncParamFlags(0)
|
||||
if len(param.Children) > 0 {
|
||||
flags |= PfDefault
|
||||
flags |= kern.PfDefault
|
||||
if defValue, err = param.Children[0].Compute(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
info := NewFuncParamFlagDef(param.Source(), flags, defValue)
|
||||
info := kern.NewFuncParamFlagDef(param.Source(), flags, defValue)
|
||||
paramList = append(paramList, info)
|
||||
}
|
||||
v = newExprFunctor(ast, paramList, ctx)
|
||||
|
||||
+55
-7
@@ -5,7 +5,9 @@
|
||||
package expr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"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 {
|
||||
if dictIt, ok := firstChildValue.(*kern.DictType); ok {
|
||||
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)
|
||||
}
|
||||
} 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 {
|
||||
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)
|
||||
}
|
||||
} else if intVal, ok := firstChildValue.(int64); ok {
|
||||
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)
|
||||
}
|
||||
} else {
|
||||
var list []any
|
||||
if list, err = evalSibling(ctx, opTerm.Children, firstChildValue); err == nil {
|
||||
v = NewArrayIterator(list)
|
||||
var siblings []any
|
||||
if siblings, err = evalSiblings(ctx, opTerm.Children, firstChildValue); err == nil {
|
||||
// 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
|
||||
}
|
||||
|
||||
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))
|
||||
for i, tree := range terms {
|
||||
var param any
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ func evalBuiltin(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
||||
} else {
|
||||
var moduleSpec any
|
||||
var it kern.Iterator
|
||||
if it, err = NewIterator(childValue); err != nil {
|
||||
if it, err = NewIterator(ctx, childValue, nil); err != nil {
|
||||
return
|
||||
}
|
||||
for moduleSpec, err = it.Next(); err == nil; moduleSpec, err = it.Next() {
|
||||
|
||||
+1
-1
@@ -111,7 +111,7 @@ func evalAssignDefault(ctx kern.ExprContext, opTerm *scan.Term) (v any, err erro
|
||||
if functor, ok := rightValue.(kern.Functor); ok {
|
||||
//ctx.RegisterFunc(leftTerm.source(), functor, 0, -1)
|
||||
ctx.RegisterFunc(leftTerm.Source(), functor, kern.TypeAny, []kern.ExprFuncParam{
|
||||
NewFuncParamFlag(kern.ParamValue, PfDefault|PfRepeat),
|
||||
kern.NewFuncParamFlag(kern.ParamValue, kern.PfDefault|kern.PfRepeat),
|
||||
})
|
||||
} else {
|
||||
v = rightValue
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ func evalDigest(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
||||
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))
|
||||
}
|
||||
|
||||
|
||||
+5
-2
@@ -28,6 +28,7 @@ func evalFilter(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
||||
var leftValue, rightValue any
|
||||
var it kern.Iterator
|
||||
var item any
|
||||
var ok bool
|
||||
|
||||
if err = opTerm.CheckOperands(); err != nil {
|
||||
return
|
||||
@@ -37,8 +38,10 @@ func evalFilter(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
if it, err = NewIterator(leftValue); err != nil {
|
||||
return nil, fmt.Errorf("left operand of FILTER must be an iterable data-source; got %s", kern.TypeName(leftValue))
|
||||
if it, ok = leftValue.(kern.Iterator); !ok {
|
||||
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()
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ func evalGroupBy(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
||||
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))
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -41,11 +41,11 @@ func evalJoin(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
||||
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))
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ func evalMap(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
||||
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))
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -100,7 +100,7 @@ func importPluginFromSearchPath(ctx kern.ExprContext, name any) (count int, err
|
||||
var it kern.Iterator
|
||||
dirList := buildSearchDirList(ctx, "plugin", ENV_EXPR_PLUGIN_PATH)
|
||||
count = 0
|
||||
if it, err = NewIterator(name); err != nil {
|
||||
if it, err = NewIterator(ctx, name, nil); err != nil {
|
||||
return
|
||||
}
|
||||
for moduleSpec, err = it.Next(); err == nil; moduleSpec, err = it.Next() {
|
||||
|
||||
+3
-3
@@ -200,12 +200,12 @@ func (ctx *SimpleStore) GetLocalFuncInfo(name string) (info kern.ExprFunc, exist
|
||||
}
|
||||
|
||||
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) {
|
||||
var info *funcInfo
|
||||
if info, err = newFuncInfo(name, functor, returnType, params); err == nil {
|
||||
var info *kern.FuncInfo
|
||||
if info, err = kern.NewFuncInfo(name, functor, returnType, params); err == nil {
|
||||
ctx.funcStore[name] = info
|
||||
exprFunc = info
|
||||
}
|
||||
|
||||
+1
-1
@@ -100,7 +100,7 @@ func TestGoFunction(t *testing.T) {
|
||||
|
||||
ctx := NewSimpleStoreWithoutGlobalContext()
|
||||
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)
|
||||
|
||||
@@ -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
@@ -61,7 +61,7 @@ func TestNewIterList2(t *testing.T) {
|
||||
|
||||
func TestNewIterList3(t *testing.T) {
|
||||
list := []any{"a", "b", "c", "d"}
|
||||
it, _ := NewIterator(list)
|
||||
it, _ := NewIterator(nil, list, nil)
|
||||
if item, err := it.Next(); err != nil {
|
||||
t.Errorf("error: %v", err)
|
||||
} else if item != "a" {
|
||||
@@ -73,7 +73,7 @@ func TestNewIterList3(t *testing.T) {
|
||||
|
||||
func TestNewIterList4(t *testing.T) {
|
||||
list := any(nil)
|
||||
it, _ := NewIterator(list)
|
||||
it, _ := NewIterator(nil, list, nil)
|
||||
if _, err := it.Next(); err != io.EOF {
|
||||
t.Errorf("error: %v", err)
|
||||
}
|
||||
@@ -81,7 +81,7 @@ func TestNewIterList4(t *testing.T) {
|
||||
|
||||
func TestNewIterList5(t *testing.T) {
|
||||
list := "123"
|
||||
it, _ := NewIterator(list)
|
||||
it, _ := NewIterator(nil, list, nil)
|
||||
if item, err := it.Next(); err != nil {
|
||||
t.Errorf("error: %v", err)
|
||||
} else if item != "123" {
|
||||
@@ -93,8 +93,8 @@ func TestNewIterList5(t *testing.T) {
|
||||
|
||||
func TestNewIterList6(t *testing.T) {
|
||||
list := kern.NewListA("a", "b", "c", "d")
|
||||
it1, _ := NewIterator(list)
|
||||
it, _ := NewIterator(it1)
|
||||
it1, _ := NewIterator(nil, list, nil)
|
||||
it, _ := NewIterator(nil, it1, nil)
|
||||
if item, err := it.Next(); err != nil {
|
||||
t.Errorf("error: %v", err)
|
||||
} else if item != "a" {
|
||||
@@ -106,7 +106,7 @@ func TestNewIterList6(t *testing.T) {
|
||||
|
||||
func TestNewString(t *testing.T) {
|
||||
list := "123"
|
||||
it, _ := NewIterator(list)
|
||||
it, _ := NewIterator(nil, list, nil)
|
||||
if s := it.String(); s != "$([#1])" {
|
||||
t.Errorf("expected $([#1]), got %s", s)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user