Merge pull request #2593 from nspcc-dev/fix-compiler
compiler: allow to call methods on return values
This commit is contained in:
commit
9414538309
5 changed files with 50 additions and 4 deletions
|
@ -918,7 +918,7 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
|
|
||||||
f, ok = c.funcs[name]
|
f, ok = c.funcs[name]
|
||||||
if ok {
|
if ok {
|
||||||
f.selector = fun.X.(*ast.Ident)
|
f.selector = fun.X
|
||||||
isBuiltin = isCustomBuiltin(f)
|
isBuiltin = isCustomBuiltin(f)
|
||||||
if canInline(f.pkg.Path(), f.decl.Name.Name) {
|
if canInline(f.pkg.Path(), f.decl.Name.Name) {
|
||||||
c.inlineCall(f, n)
|
c.inlineCall(f, n)
|
||||||
|
@ -2069,15 +2069,16 @@ func (c *codegen) getFuncFromIdent(fun *ast.Ident) (*funcScope, bool) {
|
||||||
// getFuncNameFromSelector returns fully-qualified function name from the selector expression.
|
// getFuncNameFromSelector returns fully-qualified function name from the selector expression.
|
||||||
// Second return value is true iff this was a method call, not foreign package call.
|
// Second return value is true iff this was a method call, not foreign package call.
|
||||||
func (c *codegen) getFuncNameFromSelector(e *ast.SelectorExpr) (string, bool) {
|
func (c *codegen) getFuncNameFromSelector(e *ast.SelectorExpr) (string, bool) {
|
||||||
ident := e.X.(*ast.Ident)
|
|
||||||
if c.typeInfo.Selections[e] != nil {
|
if c.typeInfo.Selections[e] != nil {
|
||||||
typ := c.typeInfo.Types[ident].Type.String()
|
typ := c.typeInfo.Types[e.X].Type.String()
|
||||||
name := c.getIdentName(typ, e.Sel.Name)
|
name := c.getIdentName(typ, e.Sel.Name)
|
||||||
if name[0] == '*' {
|
if name[0] == '*' {
|
||||||
name = name[1:]
|
name = name[1:]
|
||||||
}
|
}
|
||||||
return name, true
|
return name, true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ident := e.X.(*ast.Ident)
|
||||||
return c.getIdentName(ident.Name, e.Sel.Name), false
|
return c.getIdentName(ident.Name, e.Sel.Name), false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ type funcScope struct {
|
||||||
|
|
||||||
// Selector of the function if there is any. Only functions imported
|
// Selector of the function if there is any. Only functions imported
|
||||||
// from other packages should have a selector.
|
// from other packages should have a selector.
|
||||||
selector *ast.Ident
|
selector ast.Expr
|
||||||
|
|
||||||
// The declaration of the function in the AST. Nil if this scope is not a function.
|
// The declaration of the function in the AST. Nil if this scope is not a function.
|
||||||
decl *ast.FuncDecl
|
decl *ast.FuncDecl
|
||||||
|
|
|
@ -11,6 +11,27 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestReturnValueReceiver(t *testing.T) {
|
||||||
|
t.Run("regular", func(t *testing.T) {
|
||||||
|
src := `package foo
|
||||||
|
import "github.com/nspcc-dev/neo-go/pkg/compiler/testdata/method"
|
||||||
|
|
||||||
|
func Main() int {
|
||||||
|
return method.NewX().GetA()
|
||||||
|
}`
|
||||||
|
eval(t, src, big.NewInt(42))
|
||||||
|
})
|
||||||
|
t.Run("inline", func(t *testing.T) {
|
||||||
|
src := `package foo
|
||||||
|
import "github.com/nspcc-dev/neo-go/pkg/compiler/testdata/inline"
|
||||||
|
|
||||||
|
func Main() int {
|
||||||
|
return inline.NewT().GetN()
|
||||||
|
}`
|
||||||
|
eval(t, src, big.NewInt(42))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestSimpleFunctionCall(t *testing.T) {
|
func TestSimpleFunctionCall(t *testing.T) {
|
||||||
src := `
|
src := `
|
||||||
package testcase
|
package testcase
|
||||||
|
|
8
pkg/compiler/testdata/inline/inline.go
vendored
8
pkg/compiler/testdata/inline/inline.go
vendored
|
@ -56,3 +56,11 @@ func (t *T) Inc(i int) int {
|
||||||
t.N += i
|
t.N += i
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewT() T {
|
||||||
|
return T{N: 42}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t T) GetN() int {
|
||||||
|
return t.N
|
||||||
|
}
|
||||||
|
|
16
pkg/compiler/testdata/method/struct.go
vendored
Normal file
16
pkg/compiler/testdata/method/struct.go
vendored
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
package method
|
||||||
|
|
||||||
|
// X is some type.
|
||||||
|
type X struct {
|
||||||
|
a int
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetA returns the value of a.
|
||||||
|
func (x X) GetA() int {
|
||||||
|
return x.a
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewX creates a new X instance.
|
||||||
|
func NewX() X {
|
||||||
|
return X{a: 42}
|
||||||
|
}
|
Loading…
Reference in a new issue