github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/compiler/vardecl_test.go (about)

     1  package compiler_test
     2  
     3  import (
     4  	"math/big"
     5  	"testing"
     6  
     7  	"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
     8  )
     9  
    10  func TestGenDeclWithMultiRet(t *testing.T) {
    11  	t.Run("global var decl", func(t *testing.T) {
    12  		src := `package foo
    13  				func Main() int {
    14  					var a, b = f()
    15  					return a + b
    16  				}
    17  				func f() (int, int) {
    18  					return 1, 2
    19  				}`
    20  		eval(t, src, big.NewInt(3))
    21  	})
    22  	t.Run("local var decl", func(t *testing.T) {
    23  		src := `package foo
    24  				var a, b = f()
    25  				func Main() int {
    26  					return a + b
    27  				}
    28  				func f() (int, int) {
    29  					return 1, 2
    30  				}`
    31  		eval(t, src, big.NewInt(3))
    32  	})
    33  }
    34  
    35  func TestUnderscoreLocalVarDontEmitCode(t *testing.T) {
    36  	src := `package foo
    37  		type Foo struct { Int int }
    38  		func Main() int {
    39  			var _ int
    40  			var _ = 1
    41  			var (
    42  				A = 2
    43  				_ = A + 3
    44  				_, B, _ = 4, 5, 6
    45  				_, _, _ = f(A, B) // unused, but has function call, so the code is expected
    46  				_, C, _ = f(A, B)
    47  			)
    48  			var D = 7 // unused but named, so the code is expected
    49  			_ = D
    50  			var _ = Foo{ Int: 5 }
    51  			var fo = Foo{ Int: 3 }
    52  			var _ = 1 + A + fo.Int
    53  			var _ = fo.GetInt()	// unused, but has method call, so the code is expected
    54  			return C
    55  		}
    56  		func f(a, b int) (int, int, int) {
    57  			return 8, 9, 10
    58  		}
    59  		func (fo Foo) GetInt() int {
    60  			return fo.Int
    61  		}`
    62  	eval(t, src, big.NewInt(9), []any{opcode.INITSLOT, []byte{5, 0}}, // local slot for A, B, C, D, fo
    63  		opcode.PUSH2, opcode.STLOC0, // store A
    64  		opcode.PUSH5, opcode.STLOC1, // store B
    65  		opcode.LDLOC0, opcode.LDLOC1, opcode.SWAP, []any{opcode.CALL, []byte{27}}, // evaluate f() first time
    66  		opcode.DROP, opcode.DROP, opcode.DROP, // drop all values from f
    67  		opcode.LDLOC0, opcode.LDLOC1, opcode.SWAP, []any{opcode.CALL, []byte{19}}, // evaluate f() second time
    68  		opcode.DROP, opcode.STLOC2, opcode.DROP, // store C
    69  		opcode.PUSH7, opcode.STLOC3, // store D
    70  		opcode.LDLOC3, opcode.DROP, // empty assignment
    71  		opcode.PUSH3, opcode.PUSH1, opcode.PACKSTRUCT, opcode.STLOC4, // fo decl
    72  		opcode.LDLOC4, []any{opcode.CALL, []byte{12}}, opcode.DROP, // fo.GetInt()
    73  		opcode.LDLOC2, opcode.RET, // return C
    74  		[]any{opcode.INITSLOT, []byte{0, 2}}, opcode.PUSH10, opcode.PUSH9, opcode.PUSH8, opcode.RET, // f
    75  		[]any{opcode.INITSLOT, []byte{0, 1}}, opcode.LDARG0, opcode.PUSH0, opcode.PICKITEM, opcode.RET) // (fo Foo) GetInt() int
    76  }