2021-02-04 12:41:00 +00:00
|
|
|
package compiler
|
|
|
|
|
|
|
|
import (
|
|
|
|
"go/ast"
|
|
|
|
"go/types"
|
|
|
|
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
|
|
|
)
|
|
|
|
|
|
|
|
// inlineCall inlines call of n for function represented by f.
|
|
|
|
// Call `f(a,b)` for definition `func f(x,y int)` is translated to block:
|
|
|
|
// {
|
|
|
|
// x := a
|
|
|
|
// y := b
|
|
|
|
// <inline body of f directly>
|
|
|
|
// }
|
|
|
|
func (c *codegen) inlineCall(f *funcScope, n *ast.CallExpr) {
|
|
|
|
pkg := c.buildInfo.program.Package(f.pkg.Path())
|
|
|
|
sig := c.typeOf(n.Fun).(*types.Signature)
|
|
|
|
|
|
|
|
// Arguments need to be walked with the current scope,
|
|
|
|
// while stored in the new.
|
|
|
|
oldScope := c.scope.vars.locals
|
|
|
|
c.scope.vars.newScope()
|
|
|
|
newScope := c.scope.vars.locals
|
|
|
|
defer c.scope.vars.dropScope()
|
|
|
|
for i := range n.Args {
|
|
|
|
c.scope.vars.locals = oldScope
|
2021-02-04 13:26:33 +00:00
|
|
|
name := sig.Params().At(i).Name()
|
|
|
|
if arg, ok := n.Args[i].(*ast.Ident); ok {
|
|
|
|
// When function argument is variable or const, we may avoid
|
|
|
|
// introducing additional variables for parameters.
|
|
|
|
// This is done by providing additional alias to variable.
|
|
|
|
if vt, index := c.scope.vars.getVarIndex(arg.Name); index != -1 {
|
|
|
|
c.scope.vars.locals = newScope
|
|
|
|
c.scope.vars.addAlias(name, vt, index)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
2021-02-04 12:41:00 +00:00
|
|
|
ast.Walk(c, n.Args[i])
|
|
|
|
c.scope.vars.locals = newScope
|
|
|
|
c.scope.newLocal(name)
|
|
|
|
c.emitStoreVar("", name)
|
|
|
|
}
|
|
|
|
|
|
|
|
c.pkgInfoInline = append(c.pkgInfoInline, pkg)
|
|
|
|
oldMap := c.importMap
|
|
|
|
c.fillImportMap(f.file, pkg.Pkg)
|
|
|
|
ast.Inspect(f.decl, c.scope.analyzeVoidCalls)
|
|
|
|
ast.Walk(c, f.decl.Body)
|
|
|
|
if c.scope.voidCalls[n] {
|
|
|
|
for i := 0; i < f.decl.Type.Results.NumFields(); i++ {
|
|
|
|
emit.Opcodes(c.prog.BinWriter, opcode.DROP)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
c.importMap = oldMap
|
|
|
|
c.pkgInfoInline = c.pkgInfoInline[:len(c.pkgInfoInline)-1]
|
|
|
|
}
|