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 {
|
if t = newTerm(tk, nil); t != nil {
|
||||||
err = self.addTerm(t)
|
err = self.addTerm(t)
|
||||||
} else {
|
} else {
|
||||||
err = tk.Errorf("No term constructor for token %q", tk.String())
|
err = tk.Errorf("unexpected token %q", tk.String())
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ func TestAddTokensBad(t *testing.T) {
|
|||||||
func TestAddUnknownTokens(t *testing.T) {
|
func TestAddUnknownTokens(t *testing.T) {
|
||||||
tk0 := NewToken(0, 0, SymPercent, "%")
|
tk0 := NewToken(0, 0, SymPercent, "%")
|
||||||
|
|
||||||
wantErr := errors.New(`No term constructor for token "%"`)
|
wantErr := errors.New(`unexpected token "%"`)
|
||||||
|
|
||||||
tree := NewAst()
|
tree := NewAst()
|
||||||
if gotErr := tree.addToken(tk0); gotErr != nil && gotErr.Error() != wantErr.Error() {
|
if gotErr := tree.addToken(tk0); gotErr != nil && gotErr.Error() != wantErr.Error() {
|
||||||
|
@ -6,6 +6,7 @@ package expr
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
// -------- function call term
|
// -------- function call term
|
||||||
@ -21,6 +22,20 @@ func newFuncCallTerm(tk *Token, args []*term) *term {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// -------- eval func call
|
// -------- 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) {
|
func evalFuncCall(parentCtx ExprContext, self *term) (v any, err error) {
|
||||||
ctx := cloneContext(parentCtx)
|
ctx := cloneContext(parentCtx)
|
||||||
name, _ := self.tk.Value.(string)
|
name, _ := self.tk.Value.(string)
|
||||||
@ -34,19 +49,21 @@ func evalFuncCall(parentCtx ExprContext, self *term) (v any, err error) {
|
|||||||
params[i] = param
|
params[i] = param
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
if err = checkFunctionCall(ctx, name, params); err == nil {
|
||||||
if v, err = ctx.Call(name, params); err == nil {
|
if v, err = ctx.Call(name, params); err == nil {
|
||||||
exportObjects(parentCtx, ctx)
|
exportObjects(parentCtx, ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------- function definition term
|
// -------- function definition term
|
||||||
func newFuncDefTerm(tk *Token, args []*term) *term {
|
func newFuncDefTerm(tk *Token, args []*term) *term {
|
||||||
return &term{
|
return &term{
|
||||||
tk: *tk,
|
tk: *tk, // value is the expression body
|
||||||
parent: nil,
|
parent: nil,
|
||||||
children: args, // arg[0]=formal-param-list, arg[1]=*ast
|
children: args, // function params
|
||||||
position: posLeaf,
|
position: posLeaf,
|
||||||
priority: priValue,
|
priority: priValue,
|
||||||
evalFunc: evalFuncDef,
|
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 v, err = self.children[1].compute(ctx); err == nil {
|
||||||
if functor, ok := v.(Functor); ok {
|
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 {
|
} else {
|
||||||
ctx.setVar(leftTerm.source(), v)
|
ctx.setVar(leftTerm.source(), v)
|
||||||
}
|
}
|
||||||
|
@ -160,7 +160,7 @@ func TestParser(t *testing.T) {
|
|||||||
/* 138 */ {`nil`, nil, nil},
|
/* 138 */ {`nil`, nil, nil},
|
||||||
/* 139 */ {`null`, nil, errors.New(`undefined variable or function "null"`)},
|
/* 139 */ {`null`, nil, errors.New(`undefined variable or function "null"`)},
|
||||||
/* 140 */ {`{"key"}`, nil, errors.New(`[1:8] expected ":", got "}"`)},
|
/* 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},
|
/* 142 */ {`{}`, map[any]any{}, nil},
|
||||||
/* 143 */ {`1|2`, newFraction(1, 2), nil},
|
/* 143 */ {`1|2`, newFraction(1, 2), nil},
|
||||||
/* 144 */ {`1|2 + 1`, newFraction(3, 2), nil},
|
/* 144 */ {`1|2 + 1`, newFraction(3, 2), nil},
|
||||||
|
Loading…
Reference in New Issue
Block a user