the function call procedure now check the number of actual parameters against the numer of formal parameters
This commit is contained in:
parent
0fdd51049d
commit
1d8569d3a9
2
ast.go
2
ast.go
@ -63,7 +63,7 @@ func (self *ast) addToken2(tk *Token) (t *term, err error) {
|
||||
if t = newTerm(tk, nil); t != nil {
|
||||
err = self.addTerm(t)
|
||||
} else {
|
||||
err = tk.Errorf("No term constructor for token %q", tk.String())
|
||||
err = tk.Errorf("unexpected token %q", tk.String())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ func TestAddTokensBad(t *testing.T) {
|
||||
func TestAddUnknownTokens(t *testing.T) {
|
||||
tk0 := NewToken(0, 0, SymPercent, "%")
|
||||
|
||||
wantErr := errors.New(`No term constructor for token "%"`)
|
||||
wantErr := errors.New(`unexpected token "%"`)
|
||||
|
||||
tree := NewAst()
|
||||
if gotErr := tree.addToken(tk0); gotErr != nil && gotErr.Error() != wantErr.Error() {
|
||||
|
@ -6,6 +6,7 @@ package expr
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// -------- function call term
|
||||
@ -21,6 +22,20 @@ func newFuncCallTerm(tk *Token, args []*term) *term {
|
||||
}
|
||||
|
||||
// -------- eval func call
|
||||
func checkFunctionCall(ctx ExprContext, name string, params []any) (err error) {
|
||||
if info, exists := ctx.GetFuncInfo(name); exists {
|
||||
if info.MinArgs() > len(params) {
|
||||
err = fmt.Errorf("too few params -- expected %d, got %d", info.MinArgs(), len(params))
|
||||
}
|
||||
if info.MaxArgs() >= 0 && info.MaxArgs() < len(params) {
|
||||
err = fmt.Errorf("too much params -- expected %d, got %d", info.MaxArgs(), len(params))
|
||||
}
|
||||
} else {
|
||||
err = fmt.Errorf("unknown function %s()", name)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func evalFuncCall(parentCtx ExprContext, self *term) (v any, err error) {
|
||||
ctx := cloneContext(parentCtx)
|
||||
name, _ := self.tk.Value.(string)
|
||||
@ -34,8 +49,10 @@ func evalFuncCall(parentCtx ExprContext, self *term) (v any, err error) {
|
||||
params[i] = param
|
||||
}
|
||||
if err == nil {
|
||||
if v, err = ctx.Call(name, params); err == nil {
|
||||
exportObjects(parentCtx, ctx)
|
||||
if err = checkFunctionCall(ctx, name, params); err == nil {
|
||||
if v, err = ctx.Call(name, params); err == nil {
|
||||
exportObjects(parentCtx, ctx)
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
@ -44,9 +61,9 @@ func evalFuncCall(parentCtx ExprContext, self *term) (v any, err error) {
|
||||
// -------- function definition term
|
||||
func newFuncDefTerm(tk *Token, args []*term) *term {
|
||||
return &term{
|
||||
tk: *tk,
|
||||
tk: *tk, // value is the expression body
|
||||
parent: nil,
|
||||
children: args, // arg[0]=formal-param-list, arg[1]=*ast
|
||||
children: args, // function params
|
||||
position: posLeaf,
|
||||
priority: priValue,
|
||||
evalFunc: evalFuncDef,
|
||||
|
@ -29,7 +29,14 @@ func evalAssign(ctx ExprContext, self *term) (v any, err error) {
|
||||
|
||||
if v, err = self.children[1].compute(ctx); err == nil {
|
||||
if functor, ok := v.(Functor); ok {
|
||||
ctx.RegisterFunc(leftTerm.source(), functor, 0, -1)
|
||||
var minArgs, maxArgs int = 0, 0
|
||||
|
||||
if funcDef, ok := functor.(*funcDefFunctor); ok {
|
||||
l := len(funcDef.params)
|
||||
minArgs = l
|
||||
maxArgs = l
|
||||
}
|
||||
ctx.RegisterFunc(leftTerm.source(), functor, minArgs, maxArgs)
|
||||
} else {
|
||||
ctx.setVar(leftTerm.source(), v)
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ func TestParser(t *testing.T) {
|
||||
/* 138 */ {`nil`, nil, nil},
|
||||
/* 139 */ {`null`, nil, errors.New(`undefined variable or function "null"`)},
|
||||
/* 140 */ {`{"key"}`, nil, errors.New(`[1:8] expected ":", got "}"`)},
|
||||
/* 141 */ {`{"key":}`, nil, errors.New(`[1:9] expected dictionary value, got "}"`)},
|
||||
/* 141 */ {`{"key":}`, nil, errors.New(`[1:9] expected "dictionary-value", got "}"`)},
|
||||
/* 142 */ {`{}`, map[any]any{}, nil},
|
||||
/* 143 */ {`1|2`, newFraction(1, 2), nil},
|
||||
/* 144 */ {`1|2 + 1`, newFraction(3, 2), nil},
|
||||
|
Loading…
Reference in New Issue
Block a user