diff options
Diffstat (limited to 'vendor/github.com/d5/tengo/runtime/vm.go')
-rw-r--r-- | vendor/github.com/d5/tengo/runtime/vm.go | 63 |
1 files changed, 54 insertions, 9 deletions
diff --git a/vendor/github.com/d5/tengo/runtime/vm.go b/vendor/github.com/d5/tengo/runtime/vm.go index dde52db5..07f6e530 100644 --- a/vendor/github.com/d5/tengo/runtime/vm.go +++ b/vendor/github.com/d5/tengo/runtime/vm.go @@ -642,9 +642,31 @@ func (v *VM) run() { switch callee := value.(type) { case *objects.Closure: + if callee.Fn.VarArgs { + // if the closure is variadic, + // roll up all variadic parameters into an array + realArgs := callee.Fn.NumParameters - 1 + varArgs := numArgs - realArgs + if varArgs >= 0 { + numArgs = realArgs + 1 + args := make([]objects.Object, varArgs) + spStart := v.sp - varArgs + for i := spStart; i < v.sp; i++ { + args[i-spStart] = v.stack[i] + } + v.stack[spStart] = &objects.Array{Value: args} + v.sp = spStart + 1 + } + } + if numArgs != callee.Fn.NumParameters { - v.err = fmt.Errorf("wrong number of arguments: want=%d, got=%d", - callee.Fn.NumParameters, numArgs) + if callee.Fn.VarArgs { + v.err = fmt.Errorf("wrong number of arguments: want>=%d, got=%d", + callee.Fn.NumParameters-1, numArgs) + } else { + v.err = fmt.Errorf("wrong number of arguments: want=%d, got=%d", + callee.Fn.NumParameters, numArgs) + } return } @@ -674,9 +696,31 @@ func (v *VM) run() { v.sp = v.sp - numArgs + callee.Fn.NumLocals case *objects.CompiledFunction: + if callee.VarArgs { + // if the closure is variadic, + // roll up all variadic parameters into an array + realArgs := callee.NumParameters - 1 + varArgs := numArgs - realArgs + if varArgs >= 0 { + numArgs = realArgs + 1 + args := make([]objects.Object, varArgs) + spStart := v.sp - varArgs + for i := spStart; i < v.sp; i++ { + args[i-spStart] = v.stack[i] + } + v.stack[spStart] = &objects.Array{Value: args} + v.sp = spStart + 1 + } + } + if numArgs != callee.NumParameters { - v.err = fmt.Errorf("wrong number of arguments: want=%d, got=%d", - callee.NumParameters, numArgs) + if callee.VarArgs { + v.err = fmt.Errorf("wrong number of arguments: want>=%d, got=%d", + callee.NumParameters-1, numArgs) + } else { + v.err = fmt.Errorf("wrong number of arguments: want=%d, got=%d", + callee.NumParameters, numArgs) + } return } @@ -707,9 +751,7 @@ func (v *VM) run() { case objects.Callable: var args []objects.Object - for _, arg := range v.stack[v.sp-numArgs : v.sp] { - args = append(args, arg) - } + args = append(args, v.stack[v.sp-numArgs:v.sp]...) ret, e := callee.Call(args...) v.sp -= numArgs + 1 @@ -817,9 +859,12 @@ func (v *VM) run() { val := v.stack[v.sp-numSelectors-1] v.sp -= numSelectors + 1 - sp := v.curFrame.basePointer + localIndex + dst := v.stack[v.curFrame.basePointer+localIndex] + if obj, ok := dst.(*objects.ObjectPtr); ok { + dst = *obj.Value + } - if e := indexAssign(v.stack[sp], val, selectors); e != nil { + if e := indexAssign(dst, val, selectors); e != nil { v.err = e return } |