neo-go/pkg/compiler/vardecl_test.go
Anna Shaleva 91b36657d6 compiler: do not emit code for unnamed unused variables
If variable is unnamed and does not contain function call then it's
treated as unused and code generation may be omitted for it
initialization/declaration.
2022-09-01 09:18:56 +03:00

76 lines
2.3 KiB
Go

package compiler_test
import (
"math/big"
"testing"
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
)
func TestGenDeclWithMultiRet(t *testing.T) {
t.Run("global var decl", func(t *testing.T) {
src := `package foo
func Main() int {
var a, b = f()
return a + b
}
func f() (int, int) {
return 1, 2
}`
eval(t, src, big.NewInt(3))
})
t.Run("local var decl", func(t *testing.T) {
src := `package foo
var a, b = f()
func Main() int {
return a + b
}
func f() (int, int) {
return 1, 2
}`
eval(t, src, big.NewInt(3))
})
}
func TestUnderscoreLocalVarDontEmitCode(t *testing.T) {
src := `package foo
type Foo struct { Int int }
func Main() int {
var _ int
var _ = 1
var (
A = 2
_ = A + 3
_, B, _ = 4, 5, 6
_, _, _ = f(A, B) // unused, but has function call, so the code is expected
_, C, _ = f(A, B)
)
var D = 7 // unused but named, so the code is expected
_ = D
var _ = Foo{ Int: 5 }
var fo = Foo{ Int: 3 }
var _ = 1 + A + fo.Int
var _ = fo.GetInt() // unused, but has method call, so the code is expected
return C
}
func f(a, b int) (int, int, int) {
return 8, 9, 10
}
func (fo Foo) GetInt() int {
return fo.Int
}`
eval(t, src, big.NewInt(9), []interface{}{opcode.INITSLOT, []byte{5, 0}}, // local slot for A, B, C, D, fo
opcode.PUSH2, opcode.STLOC0, // store A
opcode.PUSH5, opcode.STLOC1, // store B
opcode.LDLOC0, opcode.LDLOC1, opcode.SWAP, []interface{}{opcode.CALL, []byte{27}}, // evaluate f() first time
opcode.DROP, opcode.DROP, opcode.DROP, // drop all values from f
opcode.LDLOC0, opcode.LDLOC1, opcode.SWAP, []interface{}{opcode.CALL, []byte{19}}, // evaluate f() second time
opcode.DROP, opcode.STLOC2, opcode.DROP, // store C
opcode.PUSH7, opcode.STLOC3, // store D
opcode.LDLOC3, opcode.DROP, // empty assignment
opcode.PUSH3, opcode.PUSH1, opcode.PACKSTRUCT, opcode.STLOC4, // fo decl
opcode.LDLOC4, []interface{}{opcode.CALL, []byte{12}}, opcode.DROP, // fo.GetInt()
opcode.LDLOC2, opcode.RET, // return C
[]interface{}{opcode.INITSLOT, []byte{0, 2}}, opcode.PUSH10, opcode.PUSH9, opcode.PUSH8, opcode.RET, // f
[]interface{}{opcode.INITSLOT, []byte{0, 1}}, opcode.LDARG0, opcode.PUSH0, opcode.PICKITEM, opcode.RET) // (fo Foo) GetInt() int
}