compiler: support initializing struct fields from a variable
While initializing a struct, it is a top item on ALTSTACK. This means that if we need to load a local variable, DUPFROMALTSTACK won't longer push an array of locals on stack but rather a currently initializing struct. Closes #656.
This commit is contained in:
parent
bcff9faac4
commit
ae03560589
2 changed files with 76 additions and 5 deletions
|
@ -872,7 +872,6 @@ func (c *codegen) convertStruct(lit *ast.CompositeLit) {
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.NOP)
|
emit.Opcode(c.prog.BinWriter, opcode.NOP)
|
||||||
emit.Int(c.prog.BinWriter, int64(strct.NumFields()))
|
emit.Int(c.prog.BinWriter, int64(strct.NumFields()))
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.NEWSTRUCT)
|
emit.Opcode(c.prog.BinWriter, opcode.NEWSTRUCT)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.TOALTSTACK)
|
|
||||||
|
|
||||||
// We need to locally store all the fields, even if they are not initialized.
|
// We need to locally store all the fields, even if they are not initialized.
|
||||||
// We will initialize all fields to their "zero" value.
|
// We will initialize all fields to their "zero" value.
|
||||||
|
@ -886,9 +885,14 @@ func (c *codegen) convertStruct(lit *ast.CompositeLit) {
|
||||||
fieldName := f.Key.(*ast.Ident).Name
|
fieldName := f.Key.(*ast.Ident).Name
|
||||||
|
|
||||||
if sField.Name() == fieldName {
|
if sField.Name() == fieldName {
|
||||||
ast.Walk(c, f.Value)
|
emit.Opcode(c.prog.BinWriter, opcode.DUP)
|
||||||
|
|
||||||
pos := indexOfStruct(strct, fieldName)
|
pos := indexOfStruct(strct, fieldName)
|
||||||
c.emitStoreLocal(pos)
|
emit.Int(c.prog.BinWriter, int64(pos))
|
||||||
|
|
||||||
|
ast.Walk(c, f.Value)
|
||||||
|
|
||||||
|
emit.Opcode(c.prog.BinWriter, opcode.SETITEM)
|
||||||
fieldAdded = true
|
fieldAdded = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -902,10 +906,12 @@ func (c *codegen) convertStruct(lit *ast.CompositeLit) {
|
||||||
c.prog.Err = err
|
c.prog.Err = err
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emit.Opcode(c.prog.BinWriter, opcode.DUP)
|
||||||
|
emit.Int(c.prog.BinWriter, int64(i))
|
||||||
c.emitLoadConst(typeAndVal)
|
c.emitLoadConst(typeAndVal)
|
||||||
c.emitStoreLocal(i)
|
emit.Opcode(c.prog.BinWriter, opcode.SETITEM)
|
||||||
}
|
}
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.FROMALTSTACK)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *codegen) convertToken(tok token.Token) {
|
func (c *codegen) convertToken(tok token.Token) {
|
||||||
|
|
|
@ -93,6 +93,71 @@ var structTestCases = []testCase{
|
||||||
`,
|
`,
|
||||||
big.NewInt(12),
|
big.NewInt(12),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"initialize struct field from variable",
|
||||||
|
`
|
||||||
|
package foo
|
||||||
|
type token struct {
|
||||||
|
x int
|
||||||
|
y int
|
||||||
|
}
|
||||||
|
|
||||||
|
func Main() int {
|
||||||
|
x := 10
|
||||||
|
t := token {
|
||||||
|
x: x,
|
||||||
|
y: 4,
|
||||||
|
}
|
||||||
|
y := t.x + t.y
|
||||||
|
return y
|
||||||
|
}`,
|
||||||
|
big.NewInt(14),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"assign a variable to a struct field",
|
||||||
|
`
|
||||||
|
package foo
|
||||||
|
type token struct {
|
||||||
|
x int
|
||||||
|
y int
|
||||||
|
}
|
||||||
|
|
||||||
|
func Main() int {
|
||||||
|
ten := 10
|
||||||
|
t := token {
|
||||||
|
x: 2,
|
||||||
|
y: 4,
|
||||||
|
}
|
||||||
|
t.x = ten
|
||||||
|
y := t.y + t.x
|
||||||
|
return y
|
||||||
|
}`,
|
||||||
|
big.NewInt(14),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"assign a struct field to a struct field",
|
||||||
|
`
|
||||||
|
package foo
|
||||||
|
type token struct {
|
||||||
|
x int
|
||||||
|
y int
|
||||||
|
}
|
||||||
|
|
||||||
|
func Main() int {
|
||||||
|
t1 := token {
|
||||||
|
x: 2,
|
||||||
|
y: 4,
|
||||||
|
}
|
||||||
|
t2 := token {
|
||||||
|
x: 3,
|
||||||
|
y: 5,
|
||||||
|
}
|
||||||
|
t1.x = t2.y
|
||||||
|
y := t1.x + t2.x
|
||||||
|
return y
|
||||||
|
}`,
|
||||||
|
big.NewInt(8),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"initialize same struct twice",
|
"initialize same struct twice",
|
||||||
`
|
`
|
||||||
|
|
Loading…
Reference in a new issue