diff --git a/pkg/compiler/analysis.go b/pkg/compiler/analysis.go index cd9e9148d..0dcc3d262 100644 --- a/pkg/compiler/analysis.go +++ b/pkg/compiler/analysis.go @@ -17,7 +17,7 @@ var ( goBuiltins = []string{"len", "append", "panic", "make", "copy", "recover", "delete"} // Custom builtin utility functions. customBuiltins = []string{ - "FromAddress", "Equals", + "FromAddress", "Equals", "Remove", "ToBool", "ToByteArray", "ToInteger", } ) diff --git a/pkg/compiler/codegen.go b/pkg/compiler/codegen.go index 7aa889e0a..8ce385f12 100644 --- a/pkg/compiler/codegen.go +++ b/pkg/compiler/codegen.go @@ -1542,6 +1542,12 @@ func (c *codegen) convertBuiltin(expr *ast.CallExpr) { typ = stackitem.BooleanT } 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": emit.Opcode(c.prog.BinWriter, opcode.EQUAL) case "FromAddress": diff --git a/pkg/compiler/slice_test.go b/pkg/compiler/slice_test.go index 7d14650d5..e4bc8c6e9 100644 --- a/pkg/compiler/slice_test.go +++ b/pkg/compiler/slice_test.go @@ -327,6 +327,30 @@ func TestSubsliceCompound(t *testing.T) { 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) { src := ` package foo diff --git a/pkg/interop/util/util.go b/pkg/interop/util/util.go index 3e80a77b0..030918f43 100644 --- a/pkg/interop/util/util.go +++ b/pkg/interop/util/util.go @@ -17,3 +17,8 @@ func FromAddress(address string) []byte { func Equals(a, b interface{}) bool { 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) { +}