From 32bce30777f968efed7bf50d304c7e6818716a83 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 10 Feb 2020 18:14:34 +0300 Subject: [PATCH 1/2] compiler: support sub-slicing --- pkg/compiler/codegen.go | 23 +++++++++++++++ pkg/compiler/slice_test.go | 59 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/pkg/compiler/codegen.go b/pkg/compiler/codegen.go index 9a9b3aa61..3d1fd43d5 100644 --- a/pkg/compiler/codegen.go +++ b/pkg/compiler/codegen.go @@ -309,6 +309,29 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor { } return nil + case *ast.SliceExpr: + name := n.X.(*ast.Ident).Name + c.emitLoadLocal(name) + + if n.Low != nil { + ast.Walk(c, n.Low) + } else { + emit.Opcode(c.prog.BinWriter, opcode.PUSH0) + } + + if n.High != nil { + ast.Walk(c, n.High) + } else { + emit.Opcode(c.prog.BinWriter, opcode.OVER) + emit.Opcode(c.prog.BinWriter, opcode.ARRAYSIZE) + } + + emit.Opcode(c.prog.BinWriter, opcode.OVER) + emit.Opcode(c.prog.BinWriter, opcode.SUB) + emit.Opcode(c.prog.BinWriter, opcode.SUBSTR) + + return nil + case *ast.ReturnStmt: l := c.newLabel() c.setLabel(l) diff --git a/pkg/compiler/slice_test.go b/pkg/compiler/slice_test.go index 1fc3abc5b..a9b0ce8f8 100644 --- a/pkg/compiler/slice_test.go +++ b/pkg/compiler/slice_test.go @@ -69,6 +69,65 @@ var sliceTestCases = []testCase{ `, big.NewInt(15), }, + { + "sub-slice with literal bounds", + ` + package foo + func Main() []byte { + a := []byte{0, 1, 2, 3} + b := a[1:3] + return b + }`, + []byte{1, 2}, + }, + { + "sub-slice with constant bounds", + ` + package foo + const x = 1 + const y = 3 + func Main() []byte { + a := []byte{0, 1, 2, 3} + b := a[x:y] + return b + }`, + []byte{1, 2}, + }, + { + "sub-slice with variable bounds", + ` + package foo + func Main() []byte { + a := []byte{0, 1, 2, 3} + x := 1 + y := 3 + b := a[x:y] + return b + }`, + []byte{1, 2}, + }, + { + "sub-slice with no lower bound", + ` + package foo + func Main() []byte { + a := []byte{0, 1, 2, 3} + b := a[:3] + return b + }`, + []byte{0, 1, 2}, + }, + { + "sub-slice with no upper bound", + ` + package foo + func Main() []byte { + a := []byte{0, 1, 2, 3} + b := a[2:] + return b + }`, + []byte{2, 3}, + }, } func TestSliceOperations(t *testing.T) { From 8ea3ef0b62e0644afbab88e8d8b0bddd2e99fec2 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 11 Feb 2020 13:15:08 +0300 Subject: [PATCH 2/2] compiler: process empty []byte{} literals as ByteArrays It is wrong to count an empty byte slice as an Array. --- pkg/compiler/analysis.go | 6 ++++++ pkg/compiler/for_test.go | 12 ++++++++++++ 2 files changed, 18 insertions(+) diff --git a/pkg/compiler/analysis.go b/pkg/compiler/analysis.go index ad46b8b93..bf3272baa 100644 --- a/pkg/compiler/analysis.go +++ b/pkg/compiler/analysis.go @@ -189,6 +189,12 @@ func isBuiltin(expr ast.Expr) bool { func isByteArray(lit *ast.CompositeLit, tInfo *types.Info) bool { if len(lit.Elts) == 0 { + if typ, ok := lit.Type.(*ast.ArrayType); ok { + if name, ok := typ.Elt.(*ast.Ident); ok { + return name.Name == "byte" || name.Name == "uint8" + } + } + return false } diff --git a/pkg/compiler/for_test.go b/pkg/compiler/for_test.go index 83b460517..6c3f67b87 100644 --- a/pkg/compiler/for_test.go +++ b/pkg/compiler/for_test.go @@ -293,6 +293,18 @@ func TestAppendByte(t *testing.T) { eval(t, src, []uint8{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06}) } +func TestAppendByteToEmpty(t *testing.T) { + src := ` + package foo + func Main() []byte { + out := []byte{} + out = append(out, 1) + out = append(out, 2) + return out + }` + eval(t, src, []byte{1, 2}) +} + func TestAppendString(t *testing.T) { src := ` package foo