Merge pull request #1391 from nspcc-dev/compiler/const

Small compiler improvements
This commit is contained in:
Roman Khimov 2020-09-07 17:46:41 +03:00 committed by GitHub
commit cf322cd9f4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 75 additions and 9 deletions

View file

@ -14,7 +14,7 @@ import (
var (
// Go language builtin functions.
goBuiltins = []string{"len", "append", "panic", "make", "copy", "recover"}
goBuiltins = []string{"len", "append", "panic", "make", "copy", "recover", "delete"}
// Custom builtin utility functions.
customBuiltins = []string{
"FromAddress", "Equals",
@ -109,8 +109,17 @@ func countGlobals(f ast.Node) (i int) {
return false
// After skipping all funcDecls we are sure that each value spec
// is a global declared variable or constant.
case *ast.ValueSpec:
i += len(n.Names)
case *ast.GenDecl:
if n.Tok == token.VAR {
for _, s := range n.Specs {
for _, id := range s.(*ast.ValueSpec).Names {
if id.Name != "_" {
i++
}
}
}
}
return false
}
return true
})

View file

@ -434,13 +434,15 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
switch t := spec.(type) {
case *ast.ValueSpec:
for _, id := range t.Names {
if c.scope == nil {
// it is a global declaration
c.newGlobal("", id.Name)
} else {
c.scope.newLocal(id.Name)
if id.Name != "_" {
if c.scope == nil {
// it is a global declaration
c.newGlobal("", id.Name)
} else {
c.scope.newLocal(id.Name)
}
c.registerDebugVariable(id.Name, t.Type)
}
c.registerDebugVariable(id.Name, t.Type)
}
for i := range t.Names {
if len(t.Values) != 0 {
@ -1525,6 +1527,8 @@ func (c *codegen) convertBuiltin(expr *ast.CallExpr) {
}
emit.Opcode(c.prog.BinWriter, opcode.PUSHNULL)
c.emitStoreByIndex(varGlobal, c.exceptionIndex)
case "delete":
emit.Opcode(c.prog.BinWriter, opcode.REMOVE)
case "ToInteger", "ToByteArray", "ToBool":
typ := stackitem.IntegerT
switch name {

View file

@ -1,6 +1,7 @@
package compiler_test
import (
"bytes"
"fmt"
"math/big"
"strings"
@ -238,3 +239,35 @@ func TestMultipleFuncSameName(t *testing.T) {
eval(t, src, big.NewInt(42))
})
}
func TestConstDontUseSlots(t *testing.T) {
const count = 256
buf := bytes.NewBufferString("package foo\n")
for i := 0; i < count; i++ {
buf.WriteString(fmt.Sprintf("const n%d = 1\n", i))
}
buf.WriteString("func Main() int { sum := 0\n")
for i := 0; i < count; i++ {
buf.WriteString(fmt.Sprintf("sum += n%d\n", i))
}
buf.WriteString("return sum }")
src := buf.String()
eval(t, src, big.NewInt(count))
}
func TestUnderscoreVarsDontUseSlots(t *testing.T) {
const count = 128
buf := bytes.NewBufferString("package foo\n")
for i := 0; i < count; i++ {
buf.WriteString(fmt.Sprintf("var _, n%d = 1, 1\n", i))
}
buf.WriteString("func Main() int { sum := 0\n")
for i := 0; i < count; i++ {
buf.WriteString(fmt.Sprintf("sum += n%d\n", i))
}
buf.WriteString("return sum }")
src := buf.String()
eval(t, src, big.NewInt(count))
}

View file

@ -55,6 +55,26 @@ var mapTestCases = []testCase{
`,
[]byte("Valera"),
},
{
"delete key",
`package foo
func Main() int {
m := map[int]int{1: 2, 3: 4}
delete(m, 1)
return len(m)
}`,
big.NewInt(1),
},
{
"delete missing key",
`package foo
func Main() int {
m := map[int]int{3: 4}
delete(m, 1)
return len(m)
}`,
big.NewInt(1),
},
}
func TestMaps(t *testing.T) {