mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-11-30 09:33:36 +00:00
Merge pull request #1401 from nspcc-dev/compiler/subslice
Support removing elements from slice.
This commit is contained in:
commit
bfe3b3d05d
5 changed files with 54 additions and 1 deletions
|
@ -32,6 +32,9 @@ pkg.go.dev](https://pkg.go.dev/github.com/nspcc-dev/neo-go/pkg/interop)
|
||||||
for full API documentation. In general it provides the same level of
|
for full API documentation. In general it provides the same level of
|
||||||
functionality as Neo .net Framework library.
|
functionality as Neo .net Framework library.
|
||||||
|
|
||||||
|
Compiler provides some helpful builtins in `util` and `convert` packages.
|
||||||
|
Refer to them for detailed documentation.
|
||||||
|
|
||||||
## Quick start
|
## Quick start
|
||||||
|
|
||||||
### Compiling
|
### Compiling
|
||||||
|
|
|
@ -17,7 +17,7 @@ var (
|
||||||
goBuiltins = []string{"len", "append", "panic", "make", "copy", "recover", "delete"}
|
goBuiltins = []string{"len", "append", "panic", "make", "copy", "recover", "delete"}
|
||||||
// Custom builtin utility functions.
|
// Custom builtin utility functions.
|
||||||
customBuiltins = []string{
|
customBuiltins = []string{
|
||||||
"FromAddress", "Equals",
|
"FromAddress", "Equals", "Remove",
|
||||||
"ToBool", "ToByteArray", "ToInteger",
|
"ToBool", "ToByteArray", "ToInteger",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -517,6 +517,10 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
case *ast.SliceExpr:
|
case *ast.SliceExpr:
|
||||||
|
if isCompoundSlice(c.typeOf(n.X.(*ast.Ident)).Underlying()) {
|
||||||
|
c.prog.Err = errors.New("subslices are supported only for []byte")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
name := n.X.(*ast.Ident).Name
|
name := n.X.(*ast.Ident).Name
|
||||||
c.emitLoadVar("", name)
|
c.emitLoadVar("", name)
|
||||||
|
|
||||||
|
@ -1538,6 +1542,12 @@ func (c *codegen) convertBuiltin(expr *ast.CallExpr) {
|
||||||
typ = stackitem.BooleanT
|
typ = stackitem.BooleanT
|
||||||
}
|
}
|
||||||
c.emitConvert(typ)
|
c.emitConvert(typ)
|
||||||
|
case "Remove":
|
||||||
|
if !isCompoundSlice(c.typeOf(expr.Args[0])) {
|
||||||
|
c.prog.Err = errors.New("`Remove` supports only non-byte slices")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
emit.Opcode(c.prog.BinWriter, opcode.REMOVE)
|
||||||
case "Equals":
|
case "Equals":
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.EQUAL)
|
emit.Opcode(c.prog.BinWriter, opcode.EQUAL)
|
||||||
case "FromAddress":
|
case "FromAddress":
|
||||||
|
|
|
@ -316,6 +316,41 @@ func TestSliceOperations(t *testing.T) {
|
||||||
runTestCases(t, sliceTestCases)
|
runTestCases(t, sliceTestCases)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSubsliceCompound(t *testing.T) {
|
||||||
|
src := `package foo
|
||||||
|
func Main() []int {
|
||||||
|
a := []int{0, 1, 2, 3}
|
||||||
|
b := a[1:3]
|
||||||
|
return b
|
||||||
|
}`
|
||||||
|
_, err := compiler.Compile("", strings.NewReader(src))
|
||||||
|
require.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRemove(t *testing.T) {
|
||||||
|
t.Run("Valid", func(t *testing.T) {
|
||||||
|
src := `package foo
|
||||||
|
import "github.com/nspcc-dev/neo-go/pkg/interop/util"
|
||||||
|
func Main() int {
|
||||||
|
a := []int{11, 22, 33}
|
||||||
|
util.Remove(a, 1)
|
||||||
|
return len(a) + a[0] + a[1]
|
||||||
|
}`
|
||||||
|
eval(t, src, big.NewInt(46))
|
||||||
|
})
|
||||||
|
t.Run("ByteSlice", func(t *testing.T) {
|
||||||
|
src := `package foo
|
||||||
|
import "github.com/nspcc-dev/neo-go/pkg/interop/util"
|
||||||
|
func Main() int {
|
||||||
|
a := []byte{11, 22, 33}
|
||||||
|
util.Remove(a, 1)
|
||||||
|
return len(a)
|
||||||
|
}`
|
||||||
|
_, err := compiler.Compile("", strings.NewReader(src))
|
||||||
|
require.Error(t, err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestJumps(t *testing.T) {
|
func TestJumps(t *testing.T) {
|
||||||
src := `
|
src := `
|
||||||
package foo
|
package foo
|
||||||
|
|
|
@ -17,3 +17,8 @@ func FromAddress(address string) []byte {
|
||||||
func Equals(a, b interface{}) bool {
|
func Equals(a, b interface{}) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove removes element with index i from slice.
|
||||||
|
// This is done in place and slice must have type other than `[]byte`.
|
||||||
|
func Remove(slice interface{}, i int) {
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue