forked from TrueCloudLab/neoneo-go
Merge pull request #654 from nspcc-dev/feat/subslice
compiler: support sub-slicing
This commit is contained in:
commit
d16121c10a
4 changed files with 100 additions and 0 deletions
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -297,6 +297,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
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue