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)
|
||||
|
||||
// If we have reached the end of the function without encountering `return` statement,
|
||||
|
@ -763,7 +776,11 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
|||
for i := len(results.List) - 1; i >= 0; i-- {
|
||||
names := results.List[i].Names
|
||||
for j := len(names) - 1; j >= 0; j-- {
|
||||
c.emitLoadVar("", names[j].Name)
|
||||
if names[j].Name == "_" {
|
||||
c.emitDefault(c.typeOf(results.List[i].Type))
|
||||
} else {
|
||||
c.emitLoadVar("", names[j].Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -120,6 +120,19 @@ func TestNamedReturn(t *testing.T) {
|
|||
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) {
|
||||
src := `
|
||||
package main
|
||||
|
|
Loading…
Reference in a new issue