Merge pull request #800 from nspcc-dev/fix/slice
compiler: declare compoud types with var keyword
This commit is contained in:
commit
6f13455cc9
4 changed files with 101 additions and 11 deletions
|
@ -187,6 +187,35 @@ func isBuiltin(expr ast.Expr) bool {
|
||||||
return false
|
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 {
|
func isByteArray(lit *ast.CompositeLit, tInfo *types.Info) bool {
|
||||||
if len(lit.Elts) == 0 {
|
if len(lit.Elts) == 0 {
|
||||||
if typ, ok := lit.Type.(*ast.ArrayType); ok {
|
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()
|
typ := tInfo.Types[lit.Elts[0]].Type.Underlying()
|
||||||
switch t := typ.(type) {
|
return isByte(typ)
|
||||||
case *types.Basic:
|
|
||||||
switch t.Kind() {
|
|
||||||
case types.Byte:
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func isSyscall(fun *funcScope) bool {
|
func isSyscall(fun *funcScope) bool {
|
||||||
|
|
|
@ -276,11 +276,23 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
for _, spec := range n.Specs {
|
for _, spec := range n.Specs {
|
||||||
switch t := spec.(type) {
|
switch t := spec.(type) {
|
||||||
case *ast.ValueSpec:
|
case *ast.ValueSpec:
|
||||||
|
if len(t.Values) != 0 {
|
||||||
for i, val := range t.Values {
|
for i, val := range t.Values {
|
||||||
ast.Walk(c, val)
|
ast.Walk(c, val)
|
||||||
l := c.scope.newLocal(t.Names[i].Name)
|
l := c.scope.newLocal(t.Names[i].Name)
|
||||||
c.emitStoreLocal(l)
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -3,6 +3,8 @@ package compiler_test
|
||||||
import (
|
import (
|
||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||||
)
|
)
|
||||||
|
|
||||||
var sliceTestCases = []testCase{
|
var sliceTestCases = []testCase{
|
||||||
|
@ -128,6 +130,35 @@ var sliceTestCases = []testCase{
|
||||||
}`,
|
}`,
|
||||||
[]byte{2, 3},
|
[]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) {
|
func TestSliceOperations(t *testing.T) {
|
||||||
|
|
|
@ -302,6 +302,31 @@ var structTestCases = []testCase{
|
||||||
`,
|
`,
|
||||||
big.NewInt(14),
|
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) {
|
func TestStructs(t *testing.T) {
|
||||||
|
|
Loading…
Reference in a new issue