CallFunction() has been replaced by three new functions:
CallFunctionByTerm(), CallFunctionByArgs() and CallFunctionByParams()
This commit is contained in:
parent
075b0b5691
commit
dceb31f542
@ -108,7 +108,7 @@ func (dc *dataCursor) Reset() (success bool, err error) {
|
||||
if dc.resetFunc != nil {
|
||||
if dc.resource != nil {
|
||||
ctx := cloneContext(dc.ctx)
|
||||
actualParams := buildActualParams(dc.resetFunc, []any{dc.resource})
|
||||
actualParams := bindActualParams(dc.resetFunc, []any{dc.resource})
|
||||
_, err = dc.resetFunc.InvokeNamed(ctx, ResetName, actualParams)
|
||||
exportObjects(dc.ctx, ctx)
|
||||
dc.index = -1
|
||||
@ -131,7 +131,7 @@ func (dc *dataCursor) Clean() (success bool, err error) {
|
||||
if dc.cleanFunc != nil {
|
||||
if dc.resource != nil {
|
||||
ctx := cloneContext(dc.ctx)
|
||||
actualParams := buildActualParams(dc.cleanFunc, []any{dc.resource})
|
||||
actualParams := bindActualParams(dc.cleanFunc, []any{dc.resource})
|
||||
_, err = dc.cleanFunc.InvokeNamed(ctx, CleanName, actualParams)
|
||||
// dc.resource = nil
|
||||
exportObjects(dc.ctx, ctx)
|
||||
@ -161,7 +161,7 @@ func (dc *dataCursor) checkFilter(filter Functor, item any) (accepted bool, err
|
||||
var ok bool
|
||||
ctx := cloneContext(dc.ctx)
|
||||
|
||||
actualParams := buildActualParams(filter, []any{item, dc.index})
|
||||
actualParams := bindActualParams(filter, []any{item, dc.index})
|
||||
if v, err = filter.InvokeNamed(ctx, FilterName, actualParams); err == nil && v != nil {
|
||||
if accepted, ok = v.(bool); !ok {
|
||||
accepted = true // NOTE: A non-boolean value that is not nil means the item has been accepted
|
||||
@ -172,7 +172,7 @@ func (dc *dataCursor) checkFilter(filter Functor, item any) (accepted bool, err
|
||||
|
||||
func (dc *dataCursor) mapItem(mapper Functor, item any) (mappedItem any, err error) {
|
||||
ctx := cloneContext(dc.ctx)
|
||||
actualParams := buildActualParams(mapper, []any{item, dc.index})
|
||||
actualParams := bindActualParams(mapper, []any{item, dc.index})
|
||||
mappedItem, err = mapper.InvokeNamed(ctx, MapName, actualParams)
|
||||
return
|
||||
}
|
||||
@ -199,7 +199,7 @@ func (dc *dataCursor) Next() (current any, err error) { // must return io.EOF af
|
||||
ctx := cloneContext(dc.ctx)
|
||||
dc.index++
|
||||
|
||||
actualParams := buildActualParams(dc.nextFunc, []any{dc.resource, dc.index})
|
||||
actualParams := bindActualParams(dc.nextFunc, []any{dc.resource, dc.index})
|
||||
if item, dc.lastErr = dc.nextFunc.InvokeNamed(ctx, NextName, actualParams); dc.lastErr == nil {
|
||||
if item == nil {
|
||||
dc.lastErr = io.EOF
|
||||
@ -238,4 +238,3 @@ func (dc *dataCursor) Index() int {
|
||||
func (dc *dataCursor) Count() int {
|
||||
return dc.count
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,8 @@ type ExprFunc interface {
|
||||
MaxArgs() int
|
||||
Functor() Functor
|
||||
Params() []ExprFuncParam
|
||||
ParamSpec(paramName string) ExprFuncParam
|
||||
ReturnType() string
|
||||
PrepareCall(parentCtx ExprContext, name string, callTerm *term) (ctx ExprContext, actualParams map[string]any, err error)
|
||||
PrepareCall(name string, actualParams map[string]any) (err error)
|
||||
AllocContext(parentCtx ExprContext) (ctx ExprContext)
|
||||
}
|
||||
|
81
function.go
81
function.go
@ -213,24 +213,23 @@ func (info *funcInfo) AllocContext(parentCtx ExprContext) (ctx ExprContext) {
|
||||
return
|
||||
}
|
||||
|
||||
func (info *funcInfo) checkExistingParam(paramName string) (exists bool) {
|
||||
exists = false
|
||||
func (info *funcInfo) ParamSpec(paramName string) ExprFuncParam {
|
||||
for _, spec := range info.formalParams {
|
||||
if spec.Name() == paramName {
|
||||
exists = true
|
||||
break
|
||||
return spec
|
||||
}
|
||||
}
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
func (info *funcInfo) initActualParams(ctx ExprContext, name string, callTerm *term) (actualParams map[string]any, err error) {
|
||||
func initActualParams(ctx ExprContext, info ExprFunc, callTerm *term) (actualParams map[string]any, err error) {
|
||||
var varArgs []any
|
||||
var varName string
|
||||
|
||||
namedParamsStarted := false
|
||||
|
||||
actualParams = make(map[string]any, len(info.formalParams))
|
||||
formalParams := info.Params()
|
||||
actualParams = make(map[string]any, len(formalParams))
|
||||
if callTerm == nil {
|
||||
return
|
||||
}
|
||||
@ -242,8 +241,8 @@ func (info *funcInfo) initActualParams(ctx ExprContext, name string, callTerm *t
|
||||
break
|
||||
}
|
||||
if paramName, namedParam := getAssignVarName(tree); namedParam {
|
||||
if !info.checkExistingParam(paramName) {
|
||||
err = fmt.Errorf("%s(): unknown param %q", name, paramName)
|
||||
if info.ParamSpec(paramName) == nil {
|
||||
err = fmt.Errorf("%s(): unknown param %q", info.Name(), paramName)
|
||||
break
|
||||
}
|
||||
actualParams[paramName] = paramValue
|
||||
@ -251,8 +250,8 @@ func (info *funcInfo) initActualParams(ctx ExprContext, name string, callTerm *t
|
||||
} else if !namedParamsStarted {
|
||||
if varArgs != nil {
|
||||
varArgs = append(varArgs, paramValue)
|
||||
} else if i < len(info.formalParams) {
|
||||
spec := info.formalParams[i]
|
||||
} else if i < len(formalParams) {
|
||||
spec := formalParams[i]
|
||||
if spec.IsRepeat() {
|
||||
varArgs = make([]any, 0, len(callTerm.children)-i)
|
||||
varArgs = append(varArgs, paramValue)
|
||||
@ -261,11 +260,11 @@ func (info *funcInfo) initActualParams(ctx ExprContext, name string, callTerm *t
|
||||
actualParams[spec.Name()] = paramValue
|
||||
}
|
||||
} else {
|
||||
err = ErrTooManyParams(name, len(info.formalParams), len(callTerm.children))
|
||||
err = ErrTooManyParams(info.Name(), len(formalParams), len(callTerm.children))
|
||||
break
|
||||
}
|
||||
} else {
|
||||
err = fmt.Errorf("%s(): positional param nr %d not allowed after named params", name, i+1)
|
||||
err = fmt.Errorf("%s(): positional param nr %d not allowed after named params", info.Name(), i+1)
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -277,14 +276,11 @@ func (info *funcInfo) initActualParams(ctx ExprContext, name string, callTerm *t
|
||||
return
|
||||
}
|
||||
|
||||
func (info *funcInfo) PrepareCall(parentCtx ExprContext, name string, callTerm *term) (ctx ExprContext, actualParams map[string]any, err error) {
|
||||
if actualParams, err = info.initActualParams(parentCtx, name, callTerm); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
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) {
|
||||
@ -304,13 +300,9 @@ func (info *funcInfo) PrepareCall(parentCtx ExprContext, name string, callTerm *
|
||||
}
|
||||
}
|
||||
|
||||
if err == nil && info.MaxArgs() >= 0 && info.MaxArgs() < len(actualParams) {
|
||||
if info.MaxArgs() >= 0 && info.MaxArgs() < len(actualParams) {
|
||||
err = ErrTooManyParams(name, info.MaxArgs(), len(actualParams))
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
ctx = info.AllocContext(parentCtx)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -323,12 +315,45 @@ func getAssignVarName(t *term) (name string, ok bool) {
|
||||
return
|
||||
}
|
||||
|
||||
func CallFunction(parentCtx ExprContext, name string, callTerm *term) (result any, err error) {
|
||||
func CallFunctionByTerm(parentCtx ExprContext, name string, callTerm *term) (result any, err error) {
|
||||
var actualParams map[string]any
|
||||
if info, exists := GetFuncInfo(parentCtx, name); exists {
|
||||
var ctx ExprContext
|
||||
if ctx, actualParams, err = info.PrepareCall(parentCtx, name, callTerm); err == nil {
|
||||
functor := info.Functor()
|
||||
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 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 ExprContext, name string, params 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)
|
||||
}
|
||||
@ -347,7 +372,7 @@ func GetParam(args map[string]any, paramName string, paramNum int) (value any, e
|
||||
return
|
||||
}
|
||||
|
||||
func buildActualParams(functor Functor, args []any) (actualParams map[string]any) {
|
||||
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 {
|
||||
|
@ -40,7 +40,7 @@ func newFuncCallTerm(tk *Token, args []*term) *term {
|
||||
|
||||
func evalFuncCall(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
name, _ := opTerm.tk.Value.(string)
|
||||
v, err = CallFunction(ctx, name, opTerm)
|
||||
v, err = CallFunctionByTerm(ctx, name, opTerm)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -103,7 +103,7 @@ func evalIterator(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
args = []any{}
|
||||
}
|
||||
|
||||
actualParams := buildActualParams(initFunc, args)
|
||||
actualParams := bindActualParams(initFunc, args)
|
||||
|
||||
initCtx := ctx.Clone()
|
||||
if resource, err = initFunc.InvokeNamed(initCtx, InitName, actualParams); err != nil {
|
||||
|
@ -63,6 +63,6 @@ func TestFuncString(t *testing.T) {
|
||||
|
||||
//t.Setenv("EXPR_PATH", ".")
|
||||
|
||||
// runTestSuiteSpec(t, section, inputs, 16)
|
||||
// runTestSuiteSpec(t, section, inputs, 19)
|
||||
runTestSuite(t, section, inputs)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user