compiler: allow to use exported constants

Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
Evgenii Stratonikov 2020-07-28 19:50:44 +03:00
parent 6df019913d
commit 528c184f00
3 changed files with 31 additions and 7 deletions

View file

@ -65,6 +65,9 @@ type codegen struct {
// importMap contains mapping from package aliases to full package names for the current file. // importMap contains mapping from package aliases to full package names for the current file.
importMap map[string]string importMap map[string]string
// constMap contains constants from foreign packages.
constMap map[string]types.TypeAndValue
// mainPkg is a main package metadata. // mainPkg is a main package metadata.
mainPkg *loader.PackageInfo mainPkg *loader.PackageInfo
@ -263,11 +266,7 @@ func (c *codegen) convertGlobals(f *ast.File, _ *types.Package) {
case *ast.FuncDecl: case *ast.FuncDecl:
return false return false
case *ast.GenDecl: case *ast.GenDecl:
// constants are loaded directly so there is no need ast.Walk(c, n)
// to store them as a local variables
if n.Tok != token.CONST {
ast.Walk(c, n)
}
} }
return true return true
}) })
@ -367,6 +366,15 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
// x = 2 // x = 2
// ) // )
case *ast.GenDecl: case *ast.GenDecl:
if n.Tok == token.CONST {
for _, spec := range n.Specs {
vs := spec.(*ast.ValueSpec)
for i := range vs.Names {
c.constMap[c.getIdentName("", vs.Names[i].Name)] = c.typeAndValueOf(vs.Values[i])
}
}
return nil
}
for _, spec := range n.Specs { for _, spec := range n.Specs {
switch t := spec.(type) { switch t := spec.(type) {
case *ast.ValueSpec: case *ast.ValueSpec:
@ -816,8 +824,12 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
if typ == nil { if typ == nil {
// This is a global variable from a package. // This is a global variable from a package.
pkgAlias := n.X.(*ast.Ident).Name pkgAlias := n.X.(*ast.Ident).Name
pkgPath := c.importMap[pkgAlias] name := c.getIdentName(pkgAlias, n.Sel.Name)
c.emitLoadVar(pkgPath, n.Sel.Name) if tv, ok := c.constMap[name]; ok {
c.emitLoadConst(tv)
} else {
c.emitLoadVar(pkgAlias, n.Sel.Name)
}
return nil return nil
} }
strct, ok := typ.Underlying().(*types.Struct) strct, ok := typ.Underlying().(*types.Struct)
@ -1480,6 +1492,7 @@ func newCodegen(info *buildInfo, pkg *loader.PackageInfo) *codegen {
globals: map[string]int{}, globals: map[string]int{},
labels: map[labelWithType]uint16{}, labels: map[labelWithType]uint16{},
typeInfo: &pkg.Info, typeInfo: &pkg.Info,
constMap: map[string]types.TypeAndValue{},
sequencePoints: make(map[string][]DebugSeqPoint), sequencePoints: make(map[string][]DebugSeqPoint),
} }

View file

@ -187,3 +187,12 @@ func TestExportedVariable(t *testing.T) {
eval(t, src, big.NewInt(46)) eval(t, src, big.NewInt(46))
}) })
} }
func TestExportedConst(t *testing.T) {
src := `package foo
import "github.com/nspcc-dev/neo-go/pkg/compiler/testdata/multi"
func Main() int {
return multi.SomeConst
}`
eval(t, src, big.NewInt(42))
}

View file

@ -1,3 +1,5 @@
package multi package multi
var SomeVar12 = 12 var SomeVar12 = 12
const SomeConst = 42