diff --git a/pkg/compiler/codegen.go b/pkg/compiler/codegen.go index e566055da..a74d4b420 100644 --- a/pkg/compiler/codegen.go +++ b/pkg/compiler/codegen.go @@ -758,6 +758,14 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor { } // Do not swap for builtin functions. if !isBuiltin { + if typ, ok := c.typeOf(n.Fun).(*types.Signature); ok && typ.Variadic() { + // pack variadic args into an array + varSize := len(n.Args) - typ.Params().Len() + 1 + c.emitReverse(varSize) + emit.Int(c.prog.BinWriter, int64(varSize)) + emit.Opcode(c.prog.BinWriter, opcode.PACK) + numArgs -= varSize - 1 + } c.emitReverse(numArgs) } @@ -1116,12 +1124,6 @@ func (c *codegen) convertSyscall(expr *ast.CallExpr, api, name string) { c.prog.Err = fmt.Errorf("unknown VM syscall api: %s", name) return } - switch name { - case "Notify": - numArgs := len(expr.Args) - emit.Int(c.prog.BinWriter, int64(numArgs)) - emit.Opcode(c.prog.BinWriter, opcode.PACK) - } emit.Syscall(c.prog.BinWriter, api) switch name { case "GetTransaction", "GetBlock": diff --git a/pkg/compiler/function_call_test.go b/pkg/compiler/function_call_test.go index 446ac0b9a..072542f58 100644 --- a/pkg/compiler/function_call_test.go +++ b/pkg/compiler/function_call_test.go @@ -184,3 +184,35 @@ func TestLocalsCount(t *testing.T) { }` eval(t, src, big.NewInt(7)) } + +func TestVariadic(t *testing.T) { + src := `package foo + func someFunc(a int, b ...int) int { + sum := a + for i := range b { + sum = sum - b[i] + } + return sum + } + func Main() int { + return someFunc(10, 1, 2, 3) + }` + eval(t, src, big.NewInt(4)) +} + +func TestVariadicMethod(t *testing.T) { + src := `package foo + type myInt int + func (x myInt) someFunc(a int, b ...int) int { + sum := int(x) + a + for i := range b { + sum = sum - b[i] + } + return sum + } + func Main() int { + x := myInt(38) + return x.someFunc(10, 1, 2, 3) + }` + eval(t, src, big.NewInt(42)) +}