Skip to content

Commit

Permalink
Rename function recv/params/results (#75)
Browse files Browse the repository at this point in the history
This PR updates the compiler to rename function params, results and
receivers, so that the identifiers don't clash with those in the
generated code.
  • Loading branch information
chriso authored Sep 25, 2023
2 parents db277c6 + d483621 commit 46d557b
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 57 deletions.
7 changes: 5 additions & 2 deletions compiler/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -372,12 +372,13 @@ func (scope *scope) compileFuncDecl(p *packages.Package, fn *ast.FuncDecl, color
// Generate the coroutine function. At this stage, use the same name
// as the source function (and require that the caller use build tags
// to disambiguate function calls).
fnType := funcTypeWithNamedResults(fn.Type)
gen := &ast.FuncDecl{
Recv: fn.Recv,
Doc: &ast.CommentGroup{},
Name: fn.Name,
Type: funcTypeWithNamedResults(fn.Type),
Body: scope.compileFuncBody(p, fn.Type, fn.Body, fn.Recv, color),
Type: fnType,
Body: scope.compileFuncBody(p, fnType, fn.Body, fn.Recv, color),
}

// If the function declaration contains function literals, we have to
Expand Down Expand Up @@ -509,6 +510,8 @@ func (scope *scope) compileFuncBody(p *packages.Package, typ *ast.FuncType, body
frameName := ast.NewIdent(fmt.Sprintf("_f%d", scope.frameIndex))
scope.frameIndex++

renameFuncRecvParamsResults(typ, recv, body, p.TypesInfo)

// Handle declarations.
//
// Types, constants and variables can be defined within any scope in the
Expand Down
41 changes: 41 additions & 0 deletions compiler/decls.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"go/ast"
"go/token"
"go/types"
"strconv"

"golang.org/x/tools/go/ast/astutil"
"golang.org/x/tools/go/packages"
Expand Down Expand Up @@ -317,3 +318,43 @@ func renameObjects(tree ast.Node, info *types.Info, decls []*ast.GenDecl, frameN
nil,
)
}

func renameFuncRecvParamsResults(typ *ast.FuncType, recv *ast.FieldList, body *ast.BlockStmt, info *types.Info) {
names := map[types.Object]*ast.Ident{}

fieldLists := []*ast.FieldList{recv, typ.Params, typ.Results}
for _, fieldList := range fieldLists {
if fieldList == nil {
continue
}
for _, field := range fieldList.List {
for _, name := range field.Names {
if name.Name == "_" {
continue
}
obj := info.ObjectOf(name)
newIdent := ast.NewIdent("_fn" + strconv.Itoa(len(names)))
names[obj] = newIdent
info.Defs[newIdent] = obj
}
}
}

decl := &ast.FuncDecl{
Recv: recv,
Type: typ,
Body: body,
}

astutil.Apply(decl, func(cursor *astutil.Cursor) bool {
switch n := cursor.Node().(type) {
case *ast.Ident:
if obj := info.ObjectOf(n); obj != nil {
if ident, ok := names[obj]; ok {
cursor.Replace(ident)
}
}
}
return true
}, nil)
}
Loading

0 comments on commit 46d557b

Please sign in to comment.