2018-01-29 Richard Biener <rguenther@suse.de>
[official-gcc.git] / libgo / go / sort / genzfunc.go
blob3bb7691f6a87f1dcace0167a08a099cc355410c5
1 // Copyright 2016 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // +build ignore
7 // This program is run via "go generate" (via a directive in sort.go)
8 // to generate zfuncversion.go.
9 //
10 // It copies sort.go to zfuncversion.go, only retaining funcs which
11 // take a "data Interface" parameter, and renaming each to have a
12 // "_func" suffix and taking a "data lessSwap" instead. It then rewrites
13 // each internal function call to the appropriate _func variants.
15 package main
17 import (
18 "bytes"
19 "go/ast"
20 "go/format"
21 "go/parser"
22 "go/token"
23 "io/ioutil"
24 "log"
25 "regexp"
28 var fset = token.NewFileSet()
30 func main() {
31 af, err := parser.ParseFile(fset, "sort.go", nil, 0)
32 if err != nil {
33 log.Fatal(err)
35 af.Doc = nil
36 af.Imports = nil
37 af.Comments = nil
39 var newDecl []ast.Decl
40 for _, d := range af.Decls {
41 fd, ok := d.(*ast.FuncDecl)
42 if !ok {
43 continue
45 if fd.Recv != nil || fd.Name.IsExported() {
46 continue
48 typ := fd.Type
49 if len(typ.Params.List) < 1 {
50 continue
52 arg0 := typ.Params.List[0]
53 arg0Name := arg0.Names[0].Name
54 arg0Type := arg0.Type.(*ast.Ident)
55 if arg0Name != "data" || arg0Type.Name != "Interface" {
56 continue
58 arg0Type.Name = "lessSwap"
60 newDecl = append(newDecl, fd)
62 af.Decls = newDecl
63 ast.Walk(visitFunc(rewriteCalls), af)
65 var out bytes.Buffer
66 if err := format.Node(&out, fset, af); err != nil {
67 log.Fatalf("format.Node: %v", err)
70 // Get rid of blank lines after removal of comments.
71 src := regexp.MustCompile(`\n{2,}`).ReplaceAll(out.Bytes(), []byte("\n"))
73 // Add comments to each func, for the lost reader.
74 // This is so much easier than adding comments via the AST
75 // and trying to get position info correct.
76 src = regexp.MustCompile(`(?m)^func (\w+)`).ReplaceAll(src, []byte("\n// Auto-generated variant of sort.go:$1\nfunc ${1}_func"))
78 // Final gofmt.
79 src, err = format.Source(src)
80 if err != nil {
81 log.Fatalf("format.Source: %v on\n%s", err, src)
84 out.Reset()
85 out.WriteString(`// DO NOT EDIT; AUTO-GENERATED from sort.go using genzfunc.go
87 // Copyright 2016 The Go Authors. All rights reserved.
88 // Use of this source code is governed by a BSD-style
89 // license that can be found in the LICENSE file.
92 out.Write(src)
94 const target = "zfuncversion.go"
95 if err := ioutil.WriteFile(target, out.Bytes(), 0644); err != nil {
96 log.Fatal(err)
100 type visitFunc func(ast.Node) ast.Visitor
102 func (f visitFunc) Visit(n ast.Node) ast.Visitor { return f(n) }
104 func rewriteCalls(n ast.Node) ast.Visitor {
105 ce, ok := n.(*ast.CallExpr)
106 if ok {
107 rewriteCall(ce)
109 return visitFunc(rewriteCalls)
112 func rewriteCall(ce *ast.CallExpr) {
113 ident, ok := ce.Fun.(*ast.Ident)
114 if !ok {
115 // e.g. skip SelectorExpr (data.Less(..) calls)
116 return
118 // skip casts
119 if ident.Name == "int" || ident.Name == "uint" {
120 return
122 if len(ce.Args) < 1 {
123 return
125 ident.Name += "_func"