Source file
src/sort/genzfunc.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package main
17
18 import (
19 "bytes"
20 "go/ast"
21 "go/format"
22 "go/parser"
23 "go/token"
24 "log"
25 "os"
26 "regexp"
27 )
28
29 var fset = token.NewFileSet()
30
31 func main() {
32 af, err := parser.ParseFile(fset, "sort.go", nil, 0)
33 if err != nil {
34 log.Fatal(err)
35 }
36 af.Doc = nil
37 af.Imports = nil
38 af.Comments = nil
39
40 var newDecl []ast.Decl
41 for _, d := range af.Decls {
42 fd, ok := d.(*ast.FuncDecl)
43 if !ok {
44 continue
45 }
46 if fd.Recv != nil || fd.Name.IsExported() {
47 continue
48 }
49 typ := fd.Type
50 if len(typ.Params.List) < 1 {
51 continue
52 }
53 arg0 := typ.Params.List[0]
54 arg0Name := arg0.Names[0].Name
55 arg0Type := arg0.Type.(*ast.Ident)
56 if arg0Name != "data" || arg0Type.Name != "Interface" {
57 continue
58 }
59 arg0Type.Name = "lessSwap"
60
61 newDecl = append(newDecl, fd)
62 }
63 af.Decls = newDecl
64 ast.Walk(visitFunc(rewriteCalls), af)
65
66 var out bytes.Buffer
67 if err := format.Node(&out, fset, af); err != nil {
68 log.Fatalf("format.Node: %v", err)
69 }
70
71
72 src := regexp.MustCompile(`\n{2,}`).ReplaceAll(out.Bytes(), []byte("\n"))
73
74
75
76
77 src = regexp.MustCompile(`(?m)^func (\w+)`).ReplaceAll(src, []byte("\n// Auto-generated variant of sort.go:$1\nfunc ${1}_func"))
78
79
80 src, err = format.Source(src)
81 if err != nil {
82 log.Fatalf("format.Source: %v on\n%s", err, src)
83 }
84
85 out.Reset()
86 out.WriteString(`// Code generated from sort.go using genzfunc.go; DO NOT EDIT.
87
88 // Copyright 2016 The Go Authors. All rights reserved.
89 // Use of this source code is governed by a BSD-style
90 // license that can be found in the LICENSE file.
91
92 `)
93 out.Write(src)
94
95 const target = "zfuncversion.go"
96 if err := os.WriteFile(target, out.Bytes(), 0644); err != nil {
97 log.Fatal(err)
98 }
99 }
100
101 type visitFunc func(ast.Node) ast.Visitor
102
103 func (f visitFunc) Visit(n ast.Node) ast.Visitor { return f(n) }
104
105 func rewriteCalls(n ast.Node) ast.Visitor {
106 ce, ok := n.(*ast.CallExpr)
107 if ok {
108 rewriteCall(ce)
109 }
110 return visitFunc(rewriteCalls)
111 }
112
113 func rewriteCall(ce *ast.CallExpr) {
114 ident, ok := ce.Fun.(*ast.Ident)
115 if !ok {
116
117 return
118 }
119
120 if ident.Name == "int" || ident.Name == "uint" {
121 return
122 }
123 if len(ce.Args) < 1 {
124 return
125 }
126 ident.Name += "_func"
127 }
128
View as plain text