compiler: allow to declare slices of compound types
Previously this declarations were ignored which resulted in runtime errors, because VM's nil is an element of primitive type and can't be converted to an array.
This commit is contained in:
parent
c738975b7b
commit
6baed7a010
3 changed files with 58 additions and 11 deletions
|
@ -187,6 +187,22 @@ func isBuiltin(expr ast.Expr) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (c *codegen) isCompoundArrayType(t ast.Expr) bool {
|
||||
switch s := t.(type) {
|
||||
case *ast.ArrayType:
|
||||
return true
|
||||
case *ast.Ident:
|
||||
arr, ok := c.typeInfo.Types[s].Type.Underlying().(*types.Slice)
|
||||
return ok && !isByte(arr.Elem())
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isByte(t types.Type) bool {
|
||||
e, ok := t.(*types.Basic)
|
||||
return ok && e.Kind() == types.Byte
|
||||
}
|
||||
|
||||
func isByteArray(lit *ast.CompositeLit, tInfo *types.Info) bool {
|
||||
if len(lit.Elts) == 0 {
|
||||
if typ, ok := lit.Type.(*ast.ArrayType); ok {
|
||||
|
@ -199,14 +215,7 @@ func isByteArray(lit *ast.CompositeLit, tInfo *types.Info) bool {
|
|||
}
|
||||
|
||||
typ := tInfo.Types[lit.Elts[0]].Type.Underlying()
|
||||
switch t := typ.(type) {
|
||||
case *types.Basic:
|
||||
switch t.Kind() {
|
||||
case types.Byte:
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return isByte(typ)
|
||||
}
|
||||
|
||||
func isSyscall(fun *funcScope) bool {
|
||||
|
|
|
@ -276,9 +276,16 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
|||
for _, spec := range n.Specs {
|
||||
switch t := spec.(type) {
|
||||
case *ast.ValueSpec:
|
||||
for i, val := range t.Values {
|
||||
ast.Walk(c, val)
|
||||
l := c.scope.newLocal(t.Names[i].Name)
|
||||
if len(t.Values) != 0 {
|
||||
for i, val := range t.Values {
|
||||
ast.Walk(c, val)
|
||||
l := c.scope.newLocal(t.Names[i].Name)
|
||||
c.emitStoreLocal(l)
|
||||
}
|
||||
} else if c.isCompoundArrayType(t.Type) {
|
||||
emit.Opcode(c.prog.BinWriter, opcode.PUSH0)
|
||||
emit.Opcode(c.prog.BinWriter, opcode.NEWARRAY)
|
||||
l := c.scope.newLocal(t.Names[0].Name)
|
||||
c.emitStoreLocal(l)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@ package compiler_test
|
|||
import (
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||
)
|
||||
|
||||
var sliceTestCases = []testCase{
|
||||
|
@ -128,6 +130,35 @@ var sliceTestCases = []testCase{
|
|||
}`,
|
||||
[]byte{2, 3},
|
||||
},
|
||||
{
|
||||
"declare compound slice",
|
||||
`package foo
|
||||
func Main() []string {
|
||||
var a []string
|
||||
a = append(a, "a")
|
||||
a = append(a, "b")
|
||||
return a
|
||||
}`,
|
||||
[]vm.StackItem{
|
||||
vm.NewByteArrayItem([]byte("a")),
|
||||
vm.NewByteArrayItem([]byte("b")),
|
||||
},
|
||||
},
|
||||
{
|
||||
"declare compound slice alias",
|
||||
`package foo
|
||||
type strs []string
|
||||
func Main() []string {
|
||||
var a strs
|
||||
a = append(a, "a")
|
||||
a = append(a, "b")
|
||||
return a
|
||||
}`,
|
||||
[]vm.StackItem{
|
||||
vm.NewByteArrayItem([]byte("a")),
|
||||
vm.NewByteArrayItem([]byte("b")),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func TestSliceOperations(t *testing.T) {
|
||||
|
|
Loading…
Reference in a new issue