mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2025-05-03 11:41:48 +00:00
compiler: do not short-circuit in complex conditions
Current implementation of short-circuting is just plain wrong as it uses `last` or `before-last` labels which meaning depend on context. It doesn't even handle simple assignements like `a := x == 1 && y == 2`. This commit makes all jumps in such conditions local and adds tests. Closes #699, #700.
This commit is contained in:
parent
26c4e83ddf
commit
b461a6ab63
2 changed files with 64 additions and 2 deletions
|
@ -1,6 +1,7 @@
|
|||
package compiler_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"strings"
|
||||
"testing"
|
||||
|
@ -704,3 +705,52 @@ func TestForLoopRangeCompilerError(t *testing.T) {
|
|||
_, err := compiler.Compile(strings.NewReader(src))
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestForLoopComplexConditions(t *testing.T) {
|
||||
src := `
|
||||
package foo
|
||||
func Main() int {
|
||||
var ok bool
|
||||
_ = ok
|
||||
i := 0
|
||||
j := 0
|
||||
%s
|
||||
for %s {
|
||||
i++
|
||||
j++
|
||||
%s
|
||||
}
|
||||
return i
|
||||
}`
|
||||
|
||||
tests := []struct {
|
||||
Name string
|
||||
Cond string
|
||||
Assign string
|
||||
Result int64
|
||||
}{
|
||||
{Cond: "i < 3 && j < 2", Result: 2},
|
||||
{Cond: "i < 3 || j < 2", Result: 3},
|
||||
{Cond: "i < 3 && (j < 2 || i < 1)", Result: 2},
|
||||
{Cond: "i < 3 && (j < 2 && i < 1)", Result: 1},
|
||||
{Cond: "(i < 1 || j < 3) && (i < 3 || j < 1)", Result: 3},
|
||||
{Cond: "(i < 2 && j < 4) || (i < 4 && j < 2)", Result: 2},
|
||||
{Cond: "ok", Assign: "ok = i < 3 && j < 2", Result: 2},
|
||||
{Cond: "ok", Assign: "ok = i < 3 || j < 2", Result: 3},
|
||||
{Cond: "ok", Assign: "ok = i < 3 && (j < 2 || i < 1)", Result: 2},
|
||||
{Cond: "ok", Assign: "ok = i < 3 && (j < 2 && i < 1)", Result: 1},
|
||||
{Cond: "ok", Assign: "ok = (i < 1 || j < 3) && (i < 3 || j < 1)", Result: 3},
|
||||
{Cond: "ok", Assign: "ok = (i < 2 && j < 4) || (i < 4 && j < 2)", Result: 2},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
name := tc.Cond
|
||||
if tc.Assign != "" {
|
||||
name = tc.Assign
|
||||
}
|
||||
t.Run(name, func(t *testing.T) {
|
||||
s := fmt.Sprintf(src, tc.Assign, tc.Cond, tc.Assign)
|
||||
eval(t, s, big.NewInt(tc.Result))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue