*: support _initialize method in contracts

Invoke `_initialize` method on every call if present.
In NEO3 there is no entrypoint and methods are invoked by offset,
thus `Main` function is no longer required.
We still have special `Main` method in tests to simplify them.
This commit is contained in:
Evgenii Stratonikov 2020-07-24 13:40:54 +03:00
parent 466af55dea
commit 685d44dbc1
9 changed files with 156 additions and 40 deletions

View file

@ -21,9 +21,6 @@ import (
"golang.org/x/tools/go/loader"
)
// The identifier of the entry function. Default set to Main.
const mainIdent = "Main"
type codegen struct {
// Information about the program with all its dependencies.
buildInfo *buildInfo
@ -62,6 +59,12 @@ type codegen struct {
// to a text span in the source file.
sequencePoints map[string][]DebugSeqPoint
// initEndOffset specifies the end of the initialization method.
initEndOffset int
// mainPkg is a main package metadata.
mainPkg *loader.PackageInfo
// Label table for recording jump destinations.
l []int
}
@ -1412,13 +1415,6 @@ func (c *codegen) newLambda(u uint16, lit *ast.FuncLit) {
}
func (c *codegen) compile(info *buildInfo, pkg *loader.PackageInfo) error {
// Resolve the entrypoint of the program.
main, mainFile := resolveEntryPoint(mainIdent, pkg)
if main == nil {
c.prog.Err = fmt.Errorf("could not find func main. Did you forget to declare it? ")
return c.prog.Err
}
funUsage := analyzeFuncUsage(pkg, info.program.AllPackages)
// Bring all imported functions into scope.
@ -1428,10 +1424,12 @@ func (c *codegen) compile(info *buildInfo, pkg *loader.PackageInfo) error {
}
}
c.traverseGlobals(mainFile)
// convert the entry point first.
c.convertFuncDecl(mainFile, main, pkg.Pkg)
c.mainPkg = pkg
n := c.traverseGlobals(pkg.Files...)
if n > 0 {
emit.Opcode(c.prog.BinWriter, opcode.RET)
c.initEndOffset = c.prog.Len()
}
// sort map keys to generate code deterministically.
keys := make([]*types.Package, 0, len(info.program.AllPackages))
@ -1451,7 +1449,7 @@ func (c *codegen) compile(info *buildInfo, pkg *loader.PackageInfo) error {
case *ast.FuncDecl:
// Don't convert the function if it's not used. This will save a lot
// of bytecode space.
if n.Name.Name != mainIdent && funUsage.funcUsed(n.Name.Name) {
if funUsage.funcUsed(n.Name.Name) {
c.convertFuncDecl(f, n, k)
}
}
@ -1497,10 +1495,8 @@ func (c *codegen) resolveFuncDecls(f *ast.File, pkg *types.Package) {
for _, decl := range f.Decls {
switch n := decl.(type) {
case *ast.FuncDecl:
if n.Name.Name != mainIdent {
c.newFunc(n)
c.funcs[n.Name.Name].pkg = pkg
}
c.newFunc(n)
c.funcs[n.Name.Name].pkg = pkg
}
}
}