mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2025-01-11 01:20:37 +00:00
parent
f70cb4f34a
commit
e58616b975
4 changed files with 80 additions and 15 deletions
|
@ -795,6 +795,20 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
emit.Call(c.prog.BinWriter, opcode.CALLL, f.label)
|
emit.Call(c.prog.BinWriter, opcode.CALLL, f.label)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if c.scope != nil && c.scope.voidCalls[n] {
|
||||||
|
var sz int
|
||||||
|
if f != nil {
|
||||||
|
sz = f.decl.Type.Results.NumFields()
|
||||||
|
} else if !isBuiltin {
|
||||||
|
// lambda invocation
|
||||||
|
f := c.typeOf(n.Fun).Underlying().(*types.Signature)
|
||||||
|
sz = f.Results().Len()
|
||||||
|
}
|
||||||
|
for i := 0; i < sz; i++ {
|
||||||
|
emit.Opcode(c.prog.BinWriter, opcode.DROP)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
case *ast.SelectorExpr:
|
case *ast.SelectorExpr:
|
||||||
|
|
|
@ -90,8 +90,24 @@ func (c *funcScope) analyzeVoidCalls(node ast.Node) bool {
|
||||||
}
|
}
|
||||||
case *ast.BinaryExpr:
|
case *ast.BinaryExpr:
|
||||||
return false
|
return false
|
||||||
|
case *ast.IfStmt:
|
||||||
|
// we can't just return `false`, because we still need to process body
|
||||||
|
ce, ok := n.Cond.(*ast.CallExpr)
|
||||||
|
if ok {
|
||||||
|
c.voidCalls[ce] = false
|
||||||
|
}
|
||||||
|
case *ast.CaseClause:
|
||||||
|
for _, e := range n.List {
|
||||||
|
ce, ok := e.(*ast.CallExpr)
|
||||||
|
if ok {
|
||||||
|
c.voidCalls[ce] = false
|
||||||
|
}
|
||||||
|
}
|
||||||
case *ast.CallExpr:
|
case *ast.CallExpr:
|
||||||
c.voidCalls[n] = true
|
_, ok := c.voidCalls[n]
|
||||||
|
if !ok {
|
||||||
|
c.voidCalls[n] = true
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -24,8 +24,8 @@ func TestSimpleFunctionCall(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNotAssignedFunctionCall(t *testing.T) {
|
func TestNotAssignedFunctionCall(t *testing.T) {
|
||||||
src := `
|
t.Run("Simple", func(t *testing.T) {
|
||||||
package testcase
|
src := `package testcase
|
||||||
func Main() int {
|
func Main() int {
|
||||||
getSomeInteger()
|
getSomeInteger()
|
||||||
getSomeInteger()
|
getSomeInteger()
|
||||||
|
@ -34,12 +34,53 @@ func TestNotAssignedFunctionCall(t *testing.T) {
|
||||||
|
|
||||||
func getSomeInteger() int {
|
func getSomeInteger() int {
|
||||||
return 0
|
return 0
|
||||||
}
|
}`
|
||||||
`
|
eval(t, src, big.NewInt(0))
|
||||||
// disable stack checks because it is hard right now
|
})
|
||||||
// to distinguish between simple function call traversal
|
t.Run("If", func(t *testing.T) {
|
||||||
// and the same traversal inside an assignment.
|
src := `package testcase
|
||||||
evalWithoutStackChecks(t, src, big.NewInt(0))
|
func f() bool { return true }
|
||||||
|
func Main() int {
|
||||||
|
if f() {
|
||||||
|
return 42
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}`
|
||||||
|
eval(t, src, big.NewInt(42))
|
||||||
|
})
|
||||||
|
t.Run("Switch", func(t *testing.T) {
|
||||||
|
src := `package testcase
|
||||||
|
func f() bool { return true }
|
||||||
|
func Main() int {
|
||||||
|
switch true {
|
||||||
|
case f():
|
||||||
|
return 42
|
||||||
|
default:
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}`
|
||||||
|
eval(t, src, big.NewInt(42))
|
||||||
|
})
|
||||||
|
t.Run("Builtin", func(t *testing.T) {
|
||||||
|
src := `package foo
|
||||||
|
import "github.com/nspcc-dev/neo-go/pkg/interop/util"
|
||||||
|
func Main() int {
|
||||||
|
util.FromAddress("NPAsqZkx9WhNd4P72uhZxBhLinSuNkxfB8")
|
||||||
|
util.FromAddress("NPAsqZkx9WhNd4P72uhZxBhLinSuNkxfB8")
|
||||||
|
return 1
|
||||||
|
}`
|
||||||
|
eval(t, src, big.NewInt(1))
|
||||||
|
})
|
||||||
|
t.Run("Lambda", func(t *testing.T) {
|
||||||
|
src := `package foo
|
||||||
|
func Main() int {
|
||||||
|
f := func() (int, int) { return 1, 2 }
|
||||||
|
f()
|
||||||
|
f()
|
||||||
|
return 42
|
||||||
|
}`
|
||||||
|
eval(t, src, big.NewInt(42))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMultipleFunctionCalls(t *testing.T) {
|
func TestMultipleFunctionCalls(t *testing.T) {
|
||||||
|
|
|
@ -32,12 +32,6 @@ func runTestCases(t *testing.T, tcases []testCase) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func evalWithoutStackChecks(t *testing.T, src string, result interface{}) {
|
|
||||||
v := vmAndCompile(t, src)
|
|
||||||
require.NoError(t, v.Run())
|
|
||||||
assertResult(t, v, result)
|
|
||||||
}
|
|
||||||
|
|
||||||
func eval(t *testing.T, src string, result interface{}) {
|
func eval(t *testing.T, src string, result interface{}) {
|
||||||
vm := vmAndCompile(t, src)
|
vm := vmAndCompile(t, src)
|
||||||
err := vm.Run()
|
err := vm.Run()
|
||||||
|
|
Loading…
Reference in a new issue