diff --git a/pkg/compiler/codegen.go b/pkg/compiler/codegen.go index 3df5ffa43..7866fe5e7 100644 --- a/pkg/compiler/codegen.go +++ b/pkg/compiler/codegen.go @@ -594,15 +594,11 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor { return nil case *ast.CompositeLit: - typ := c.typeOf(n.Type).Underlying() - switch n.Type.(type) { - case *ast.Ident, *ast.SelectorExpr, *ast.MapType: - switch typ.(type) { - case *types.Struct: - c.convertStruct(n) - case *types.Map: - c.convertMap(n) - } + switch typ := c.typeOf(n).Underlying().(type) { + case *types.Struct: + c.convertStruct(n) + case *types.Map: + c.convertMap(n) default: ln := len(n.Elts) // ByteArrays needs a different approach than normal arrays. @@ -1257,12 +1253,25 @@ func (c *codegen) convertStruct(lit *ast.CompositeLit) { emit.Int(c.prog.BinWriter, int64(strct.NumFields())) emit.Opcode(c.prog.BinWriter, opcode.NEWSTRUCT) + keyedLit := len(lit.Elts) > 0 + if keyedLit { + _, ok := lit.Elts[0].(*ast.KeyValueExpr) + keyedLit = keyedLit && ok + } // We need to locally store all the fields, even if they are not initialized. // We will initialize all fields to their "zero" value. for i := 0; i < strct.NumFields(); i++ { sField := strct.Field(i) fieldAdded := false + if !keyedLit { + emit.Opcode(c.prog.BinWriter, opcode.DUP) + emit.Int(c.prog.BinWriter, int64(i)) + ast.Walk(c, lit.Elts[i]) + emit.Opcode(c.prog.BinWriter, opcode.SETITEM) + continue + } + // Fields initialized by the program. for _, field := range lit.Elts { f := field.(*ast.KeyValueExpr) diff --git a/pkg/compiler/slice_test.go b/pkg/compiler/slice_test.go index b90283a2a..2dfe9adbc 100644 --- a/pkg/compiler/slice_test.go +++ b/pkg/compiler/slice_test.go @@ -222,6 +222,27 @@ var sliceTestCases = []testCase{ }`, big.NewInt(42), }, + { + "nested slice omitted type (slice)", + `package foo + func Main() int { + a := [][]int{{1, 2}, {3, 4}} + a[1][0] = 42 + return a[1][0] + }`, + big.NewInt(42), + }, + { + "nested slice omitted type (struct)", + `package foo + type pair struct { a, b int } + func Main() int { + a := []pair{{a: 1, b: 2}, {a: 3, b: 4}} + a[1].a = 42 + return a[1].a + }`, + big.NewInt(42), + }, } func TestSliceOperations(t *testing.T) { diff --git a/pkg/compiler/struct_test.go b/pkg/compiler/struct_test.go index b11b55ac0..945273d28 100644 --- a/pkg/compiler/struct_test.go +++ b/pkg/compiler/struct_test.go @@ -394,6 +394,17 @@ var structTestCases = []testCase{ }`, big.NewInt(42), }, + { + "omit field names", + `package foo + type pair struct { a, b int } + func Main() int { + p := pair{1, 2} + x := p.a * 10 + return x + p.b + }`, + big.NewInt(12), + }, } func TestStructs(t *testing.T) {