perform arg type checking and evaluation before function call

This commit is contained in:
Aidan 2020-08-21 01:37:04 -07:00
parent 90284f2d06
commit ab340ceb0a
No known key found for this signature in database
GPG key ID: 327711E983899316
9 changed files with 223 additions and 354 deletions

View file

@ -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")