Merge pull request #800 from nspcc-dev/fix/slice

compiler: declare compoud types with var keyword
This commit is contained in:
Roman Khimov 2020-03-30 00:14:59 +03:00 committed by GitHub
commit 6f13455cc9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 101 additions and 11 deletions

View file

@ -187,6 +187,35 @@ 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 (c *codegen) isStructType(t ast.Expr) (int, bool) {
switch s := t.(type) {
case *ast.StructType:
return s.Fields.NumFields(), true
case *ast.Ident:
st, ok := c.typeInfo.Types[s].Type.Underlying().(*types.Struct)
if ok {
return st.NumFields(), true
}
}
return 0, false
}
func isByteArray(lit *ast.CompositeLit, tInfo *types.Info) bool {
if len(lit.Elts) == 0 {
if typ, ok := lit.Type.(*ast.ArrayType); ok {
@ -199,14 +228,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 {

View file

@ -276,9 +276,21 @@ 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)
} else if n, ok := c.isStructType(t.Type); ok {
emit.Int(c.prog.BinWriter, int64(n))
emit.Opcode(c.prog.BinWriter, opcode.NEWSTRUCT)
l := c.scope.newLocal(t.Names[0].Name)
c.emitStoreLocal(l)
}
}

View file

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

View file

@ -302,6 +302,31 @@ var structTestCases = []testCase{
`,
big.NewInt(14),
},
{
"declare struct literal",
`package foo
func Main() int {
var x struct {
a int
}
x.a = 2
return x.a
}`,
big.NewInt(2),
},
{
"declare struct type",
`package foo
type withA struct {
a int
}
func Main() int {
var x withA
x.a = 2
return x.a
}`,
big.NewInt(2),
},
}
func TestStructs(t *testing.T) {