From 1d275ceb65659e95a5fdc6f76121efb5787ee7ef Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 24 Jun 2020 18:36:21 +0300 Subject: [PATCH] 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. --- pkg/compiler/codegen.go | 13 ++++++++++--- pkg/compiler/convert_test.go | 14 ++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/pkg/compiler/codegen.go b/pkg/compiler/codegen.go index 7f565ab3d..7e838946c 100644 --- a/pkg/compiler/codegen.go +++ b/pkg/compiler/codegen.go @@ -712,6 +712,7 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor { name string numArgs = len(n.Args) isBuiltin bool + isFunc bool ) switch fun := n.Fun.(type) { @@ -721,6 +722,10 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor { if !ok && !isBuiltin { name = fun.Name } + // distinguish lambda invocations from type conversions + if fun.Obj != nil && fun.Obj.Kind == ast.Var { + isFunc = true + } case *ast.SelectorExpr: // 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 @@ -767,9 +772,11 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor { // We can be sure builtins are of type *ast.Ident. c.convertBuiltin(n) case name != "": - // Function was not found thus is can be only an invocation of func-typed variable. - c.emitLoadVar(name) - emit.Opcode(c.prog.BinWriter, opcode.CALLA) + // Function was not found thus is can be only an invocation of func-typed variable or type conversion. + if isFunc { + c.emitLoadVar(name) + emit.Opcode(c.prog.BinWriter, opcode.CALLA) + } case isSyscall(f): c.convertSyscall(n, f.selector.Name, f.name) default: diff --git a/pkg/compiler/convert_test.go b/pkg/compiler/convert_test.go index e768d7573..613e1af3a 100644 --- a/pkg/compiler/convert_test.go +++ b/pkg/compiler/convert_test.go @@ -72,3 +72,17 @@ func TestTypeAssertion(t *testing.T) { }` 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)) +}