forked from TrueCloudLab/neoneo-go
compiler: Initialize named returns to default values
Make them behave as locals. We must initialize them at the start because the default value could also be used inside the function body. Signed-off-by: Evgenii Stratonikov <fyfyrchik@runbox.com>
This commit is contained in:
parent
f2bb4d455b
commit
78cefca5c9
2 changed files with 31 additions and 1 deletions
|
@ -522,6 +522,19 @@ func (c *codegen) convertFuncDecl(file ast.Node, decl *ast.FuncDecl, pkg *types.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Emit defaults for named returns.
|
||||||
|
if decl.Type.Results.NumFields() != 0 {
|
||||||
|
for _, arg := range decl.Type.Results.List {
|
||||||
|
for _, id := range arg.Names {
|
||||||
|
if id.Name != "_" {
|
||||||
|
i := c.scope.newLocal(id.Name)
|
||||||
|
c.emitDefault(c.typeOf(arg.Type))
|
||||||
|
c.emitStoreByIndex(varLocal, i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ast.Walk(c, decl.Body)
|
ast.Walk(c, decl.Body)
|
||||||
|
|
||||||
// If we have reached the end of the function without encountering `return` statement,
|
// If we have reached the end of the function without encountering `return` statement,
|
||||||
|
@ -763,10 +776,14 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
for i := len(results.List) - 1; i >= 0; i-- {
|
for i := len(results.List) - 1; i >= 0; i-- {
|
||||||
names := results.List[i].Names
|
names := results.List[i].Names
|
||||||
for j := len(names) - 1; j >= 0; j-- {
|
for j := len(names) - 1; j >= 0; j-- {
|
||||||
|
if names[j].Name == "_" {
|
||||||
|
c.emitDefault(c.typeOf(results.List[i].Type))
|
||||||
|
} else {
|
||||||
c.emitLoadVar("", names[j].Name)
|
c.emitLoadVar("", names[j].Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// first result should be on top of the stack
|
// first result should be on top of the stack
|
||||||
for i := len(n.Results) - 1; i >= 0; i-- {
|
for i := len(n.Results) - 1; i >= 0; i-- {
|
||||||
|
|
|
@ -120,6 +120,19 @@ func TestNamedReturn(t *testing.T) {
|
||||||
t.Run("AnotherVariable", runCase("b, c", big.NewInt(5)))
|
t.Run("AnotherVariable", runCase("b, c", big.NewInt(5)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNamedReturnDefault(t *testing.T) {
|
||||||
|
src := `package foo
|
||||||
|
func Main() int {
|
||||||
|
a, b, c := f()
|
||||||
|
return a + b + c
|
||||||
|
}
|
||||||
|
func f() (_ int, b int, c int) {
|
||||||
|
b += 1
|
||||||
|
return
|
||||||
|
}`
|
||||||
|
eval(t, src, big.NewInt(1))
|
||||||
|
}
|
||||||
|
|
||||||
func TestTypeAssertReturn(t *testing.T) {
|
func TestTypeAssertReturn(t *testing.T) {
|
||||||
src := `
|
src := `
|
||||||
package main
|
package main
|
||||||
|
|
Loading…
Reference in a new issue