mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-11-26 09:42:22 +00:00
compiler: distinguish between type conversions and function calls
RN every identifier in call expression is considered to be lambda. But it also can be type expression, so we need to distinguish between these cases.
This commit is contained in:
parent
904b2136fc
commit
1d275ceb65
2 changed files with 24 additions and 3 deletions
|
@ -712,6 +712,7 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
name string
|
name string
|
||||||
numArgs = len(n.Args)
|
numArgs = len(n.Args)
|
||||||
isBuiltin bool
|
isBuiltin bool
|
||||||
|
isFunc bool
|
||||||
)
|
)
|
||||||
|
|
||||||
switch fun := n.Fun.(type) {
|
switch fun := n.Fun.(type) {
|
||||||
|
@ -721,6 +722,10 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
if !ok && !isBuiltin {
|
if !ok && !isBuiltin {
|
||||||
name = fun.Name
|
name = fun.Name
|
||||||
}
|
}
|
||||||
|
// distinguish lambda invocations from type conversions
|
||||||
|
if fun.Obj != nil && fun.Obj.Kind == ast.Var {
|
||||||
|
isFunc = true
|
||||||
|
}
|
||||||
case *ast.SelectorExpr:
|
case *ast.SelectorExpr:
|
||||||
// If this is a method call we need to walk the AST to load the struct locally.
|
// If this is a method call we need to walk the AST to load the struct locally.
|
||||||
// Otherwise this is a function call from a imported package and we can call it
|
// Otherwise this is a function call from a imported package and we can call it
|
||||||
|
@ -767,9 +772,11 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
// We can be sure builtins are of type *ast.Ident.
|
// We can be sure builtins are of type *ast.Ident.
|
||||||
c.convertBuiltin(n)
|
c.convertBuiltin(n)
|
||||||
case name != "":
|
case name != "":
|
||||||
// Function was not found thus is can be only an invocation of func-typed variable.
|
// Function was not found thus is can be only an invocation of func-typed variable or type conversion.
|
||||||
|
if isFunc {
|
||||||
c.emitLoadVar(name)
|
c.emitLoadVar(name)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.CALLA)
|
emit.Opcode(c.prog.BinWriter, opcode.CALLA)
|
||||||
|
}
|
||||||
case isSyscall(f):
|
case isSyscall(f):
|
||||||
c.convertSyscall(n, f.selector.Name, f.name)
|
c.convertSyscall(n, f.selector.Name, f.name)
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -72,3 +72,17 @@ func TestTypeAssertion(t *testing.T) {
|
||||||
}`
|
}`
|
||||||
eval(t, src, big.NewInt(1))
|
eval(t, src, big.NewInt(1))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTypeConversion(t *testing.T) {
|
||||||
|
src := `package foo
|
||||||
|
type myInt int
|
||||||
|
func Main() int32 {
|
||||||
|
var a int32 = 41
|
||||||
|
b := myInt(a)
|
||||||
|
incMy := func(x myInt) myInt { return x + 1 }
|
||||||
|
c := incMy(b)
|
||||||
|
return int32(c)
|
||||||
|
}`
|
||||||
|
|
||||||
|
eval(t, src, big.NewInt(42))
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue