perform arg type checking and evaluation before function call
This commit is contained in:
parent
90284f2d06
commit
ab340ceb0a
9 changed files with 223 additions and 354 deletions
|
|
@ -38,8 +38,18 @@ type Function struct {
|
|||
// number of times user has called this function
|
||||
TimesCalled int
|
||||
|
||||
// number of args required
|
||||
Args int
|
||||
// list of types (LIST, NUMBER, STRING, etc) representing args
|
||||
Args []Token_t
|
||||
NumArgs bool // -1 means infinite
|
||||
|
||||
// lazy arg checking (use NumArgs instead of args)
|
||||
ArgLazy bool
|
||||
|
||||
// dont fail on undefined symbol (passed to eval when parsing args)
|
||||
SymLazy bool
|
||||
|
||||
// dont eval args at all, leave that to the function
|
||||
EvalLazy bool
|
||||
}
|
||||
|
||||
/* holds a mapping of key to function
|
||||
|
|
@ -52,24 +62,52 @@ type FuncTable *map[string]*Function
|
|||
* makes sure correct arguments are passed in
|
||||
*/
|
||||
func (f Function) ParseFunction(args *Token) bool {
|
||||
// handle infinite args
|
||||
if f.Args < 0 {
|
||||
total = len(f.Args)
|
||||
for iter := args; iter != nil; iter = iter.Next {
|
||||
total -= 1
|
||||
if total <= 0 {
|
||||
log.Log(log.ERR,
|
||||
"too many arguments",
|
||||
"ftable")
|
||||
return false
|
||||
}
|
||||
|
||||
if iter.Tag != f.Args[len(f.Args) - total] {
|
||||
log.Log(log.ERR,
|
||||
"argument of type " + GetTagAsStr(iter.Tag) +
|
||||
"passed in when " + GetTagAsStr(f.Args[len(f.Args) - total]) +
|
||||
" was expected",
|
||||
"ftable")
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
/* same as ParseFunction but only evaluates the number of args
|
||||
*/
|
||||
func (f Function) LazyParseFunction(args *Token) bool {
|
||||
if (f.NumArgs < 0) {
|
||||
return true
|
||||
}
|
||||
|
||||
i := f.Args
|
||||
total := 0
|
||||
for iter := args; iter != nil; iter = iter.Next {
|
||||
i -= 1
|
||||
total += 1
|
||||
}
|
||||
|
||||
if i != 0 {
|
||||
if total < f.NumArgs {
|
||||
log.Log(log.ERR,
|
||||
"Incorrect number of arguments",
|
||||
"eval")
|
||||
log.Log(log.DEBUG,
|
||||
fmt.Sprintf("Function %s expects %d arguments. You've provided %d arguments.",
|
||||
f.Name, f.Args, f.Args - i),
|
||||
"eval")
|
||||
"expected more arguments, try calling info on function",
|
||||
"ftable")
|
||||
return false
|
||||
}
|
||||
|
||||
if total > f.NumArgs {
|
||||
log.Log(log.ERR,
|
||||
"too many args. try calling info on function",
|
||||
"ftable")
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
@ -80,7 +118,18 @@ func (f Function) ParseFunction(args *Token) bool {
|
|||
* calls ParseFunction and increments TimesCalled
|
||||
*/
|
||||
func (f Function) CallFunction(args *Token, vt VarTable, ft FuncTable) *Token {
|
||||
if !f.ParseFunction(args) {
|
||||
if not f.EvalLazy {
|
||||
args = args.Eval(ft, vt, !f.SymLazy)
|
||||
}
|
||||
|
||||
passes := false
|
||||
if f.ArgsLazy {
|
||||
passes = LazyParseFunction(args)
|
||||
} else {
|
||||
passes = ParseFunction(args)
|
||||
}
|
||||
|
||||
if passes {
|
||||
log.Log(log.ERR,
|
||||
"Couldnt call " + f.Name,
|
||||
"eval")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue