forked from TrueCloudLab/neoneo-go
compiler: support ellipsis for append of non-byte slices
NeoVM lacks opcode for array append, thus some kind of loop is needed for this.
This commit is contained in:
parent
fc3b840335
commit
d16ef53653
2 changed files with 43 additions and 4 deletions
|
@ -1635,10 +1635,32 @@ func (c *codegen) convertBuiltin(expr *ast.CallExpr) {
|
|||
} else {
|
||||
emit.Instruction(c.prog.BinWriter, opcode.JMPIFNOT, []byte{2 + 2})
|
||||
emit.Opcodes(c.prog.BinWriter, opcode.DROP, opcode.NEWARRAY0)
|
||||
for _, e := range expr.Args[1:] {
|
||||
emit.Opcodes(c.prog.BinWriter, opcode.DUP)
|
||||
ast.Walk(c, e)
|
||||
emit.Opcodes(c.prog.BinWriter, opcode.APPEND)
|
||||
if expr.Ellipsis.IsValid() {
|
||||
ast.Walk(c, expr.Args[1]) // x y
|
||||
emit.Opcodes(c.prog.BinWriter, opcode.PUSH0) // x y cnt=0
|
||||
start := c.newLabel()
|
||||
c.setLabel(start)
|
||||
emit.Opcodes(c.prog.BinWriter, opcode.PUSH2, opcode.PICK) // x y cnt x
|
||||
emit.Opcodes(c.prog.BinWriter, opcode.PUSH2, opcode.PICK) // x y cnt x y
|
||||
emit.Opcodes(c.prog.BinWriter, opcode.DUP, opcode.SIZE) // x y cnt x y len(y)
|
||||
emit.Opcodes(c.prog.BinWriter, opcode.PUSH3, opcode.PICK) // x y cnt x y len(y) cnt
|
||||
after := c.newLabel()
|
||||
emit.Jmp(c.prog.BinWriter, opcode.JMPEQL, after) // x y cnt x y
|
||||
emit.Opcodes(c.prog.BinWriter, opcode.PUSH2, opcode.PICK, // x y cnt x y cnt
|
||||
opcode.PICKITEM, // x y cnt x y[cnt]
|
||||
opcode.APPEND, // x=append(x, y[cnt]) y cnt
|
||||
opcode.INC) // x y cnt+1
|
||||
emit.Jmp(c.prog.BinWriter, opcode.JMPL, start)
|
||||
c.setLabel(after)
|
||||
for i := 0; i < 4; i++ { // leave x on stack
|
||||
emit.Opcodes(c.prog.BinWriter, opcode.DROP)
|
||||
}
|
||||
} else {
|
||||
for _, e := range expr.Args[1:] {
|
||||
emit.Opcodes(c.prog.BinWriter, opcode.DUP)
|
||||
ast.Walk(c, e)
|
||||
emit.Opcodes(c.prog.BinWriter, opcode.APPEND)
|
||||
}
|
||||
}
|
||||
}
|
||||
case "panic":
|
||||
|
|
|
@ -181,6 +181,23 @@ var sliceTestCases = []testCase{
|
|||
stackitem.NewBigInteger(big.NewInt(5)),
|
||||
},
|
||||
},
|
||||
{
|
||||
"int slice, append slice",
|
||||
`package foo
|
||||
func getByte() byte { return 0x80 }
|
||||
func Main() []int {
|
||||
x := []int{1}
|
||||
y := []int{2, 3}
|
||||
x = append(x, y...)
|
||||
x = append(x, y...)
|
||||
return x
|
||||
}`,
|
||||
[]stackitem.Item{
|
||||
stackitem.Make(1),
|
||||
stackitem.Make(2), stackitem.Make(3),
|
||||
stackitem.Make(2), stackitem.Make(3),
|
||||
},
|
||||
},
|
||||
{
|
||||
"declare compound slice",
|
||||
`package foo
|
||||
|
|
Loading…
Reference in a new issue