compiler: support sub-slicing

This commit is contained in:
Evgenii Stratonikov 2020-02-10 18:14:34 +03:00
parent bcff9faac4
commit 32bce30777
2 changed files with 82 additions and 0 deletions

View file

@ -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)

View file

@ -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) {