Merge pull request #1425 from nspcc-dev/compiler/byteslice
Support variables in slice literals.
This commit is contained in:
commit
4b0008708b
4 changed files with 58 additions and 2 deletions
|
@ -1594,13 +1594,24 @@ func (c *codegen) emitConvert(typ stackitem.Type) {
|
||||||
|
|
||||||
func (c *codegen) convertByteArray(lit *ast.CompositeLit) {
|
func (c *codegen) convertByteArray(lit *ast.CompositeLit) {
|
||||||
buf := make([]byte, len(lit.Elts))
|
buf := make([]byte, len(lit.Elts))
|
||||||
|
varIndices := []int{}
|
||||||
for i := 0; i < len(lit.Elts); i++ {
|
for i := 0; i < len(lit.Elts); i++ {
|
||||||
t := c.typeAndValueOf(lit.Elts[i])
|
t := c.typeAndValueOf(lit.Elts[i])
|
||||||
|
if t.Value != nil {
|
||||||
val, _ := constant.Int64Val(t.Value)
|
val, _ := constant.Int64Val(t.Value)
|
||||||
buf[i] = byte(val)
|
buf[i] = byte(val)
|
||||||
|
} else {
|
||||||
|
varIndices = append(varIndices, i)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
emit.Bytes(c.prog.BinWriter, buf)
|
emit.Bytes(c.prog.BinWriter, buf)
|
||||||
c.emitConvert(stackitem.BufferT)
|
c.emitConvert(stackitem.BufferT)
|
||||||
|
for _, i := range varIndices {
|
||||||
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *codegen) convertMap(lit *ast.CompositeLit) {
|
func (c *codegen) convertMap(lit *ast.CompositeLit) {
|
||||||
|
|
|
@ -136,6 +136,18 @@ func (c *funcScope) analyzeVoidCalls(node ast.Node) bool {
|
||||||
c.voidCalls[n] = true
|
c.voidCalls[n] = true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
case *ast.CompositeLit:
|
||||||
|
for _, e := range n.Elts {
|
||||||
|
switch val := e.(type) {
|
||||||
|
case *ast.CallExpr: // slice
|
||||||
|
c.voidCalls[val] = false
|
||||||
|
case *ast.KeyValueExpr: // struct and map
|
||||||
|
ce, ok := val.Value.(*ast.CallExpr)
|
||||||
|
if ok {
|
||||||
|
c.voidCalls[ce] = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -310,6 +310,26 @@ var sliceTestCases = []testCase{
|
||||||
`,
|
`,
|
||||||
big.NewInt(2),
|
big.NewInt(2),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"literal byte-slice with variable values",
|
||||||
|
`package foo
|
||||||
|
const sym1 = 's'
|
||||||
|
func Main() []byte {
|
||||||
|
sym2 := byte('t')
|
||||||
|
sym4 := byte('i')
|
||||||
|
return []byte{sym1, sym2, 'r', sym4, 'n', 'g'}
|
||||||
|
}`,
|
||||||
|
[]byte("string"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"literal slice with function call",
|
||||||
|
`package foo
|
||||||
|
func fn() byte { return 't' }
|
||||||
|
func Main() []byte {
|
||||||
|
return []byte{'s', fn(), 'r'}
|
||||||
|
}`,
|
||||||
|
[]byte("str"),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSliceOperations(t *testing.T) {
|
func TestSliceOperations(t *testing.T) {
|
||||||
|
|
|
@ -29,6 +29,19 @@ var structTestCases = []testCase{
|
||||||
`,
|
`,
|
||||||
big.NewInt(2),
|
big.NewInt(2),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"struct field from func result",
|
||||||
|
`
|
||||||
|
package foo
|
||||||
|
type S struct { x int }
|
||||||
|
func fn() int { return 2 }
|
||||||
|
func Main() int {
|
||||||
|
t := S{x: fn()}
|
||||||
|
return t.x
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
big.NewInt(2),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"struct field return",
|
"struct field return",
|
||||||
`
|
`
|
||||||
|
|
Loading…
Reference in a new issue