OLD | NEW |
(Empty) | |
| 1 // Copyright 2009 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. |
| 4 |
| 5 package main |
| 6 |
| 7 import ( |
| 8 "fmt"; |
| 9 "go/ast"; |
| 10 "go/parser"; |
| 11 "go/token"; |
| 12 "os"; |
| 13 "reflect"; |
| 14 "strings"; |
| 15 "unicode"; |
| 16 "utf8"; |
| 17 ) |
| 18 |
| 19 |
| 20 func initRewrite() { |
| 21 if *rewriteRule == "" { |
| 22 return |
| 23 } |
| 24 f := strings.Split(*rewriteRule, "->", 0); |
| 25 if len(f) != 2 { |
| 26 fmt.Fprintf(os.Stderr, "rewrite rule must be of the form 'patter
n -> replacement'\n"); |
| 27 os.Exit(2); |
| 28 } |
| 29 pattern := parseExpr(f[0], "pattern"); |
| 30 replace := parseExpr(f[1], "replacement"); |
| 31 rewrite = func(p *ast.File) *ast.File { return rewriteFile(pattern, repl
ace, p) }; |
| 32 } |
| 33 |
| 34 |
| 35 // parseExpr parses s as an expression. |
| 36 // It might make sense to expand this to allow statement patterns, |
| 37 // but there are problems with preserving formatting and also |
| 38 // with what a wildcard for a statement looks like. |
| 39 func parseExpr(s string, what string) ast.Expr { |
| 40 stmts, err := parser.ParseStmtList("input", s); |
| 41 if err != nil { |
| 42 fmt.Fprintf(os.Stderr, "parsing %s %s: %s\n", what, s, err); |
| 43 os.Exit(2); |
| 44 } |
| 45 if len(stmts) != 1 { |
| 46 fmt.Fprintf(os.Stderr, "%s must be single expression\n", what); |
| 47 os.Exit(2); |
| 48 } |
| 49 x, ok := stmts[0].(*ast.ExprStmt); |
| 50 if !ok { |
| 51 fmt.Fprintf(os.Stderr, "%s must be single expression\n", what); |
| 52 os.Exit(2); |
| 53 } |
| 54 return x.X; |
| 55 } |
| 56 |
| 57 |
| 58 // rewriteFile applys the rewrite rule pattern -> replace to an entire file. |
| 59 func rewriteFile(pattern, replace ast.Expr, p *ast.File) *ast.File { |
| 60 m := make(map[string]reflect.Value); |
| 61 pat := reflect.NewValue(pattern); |
| 62 repl := reflect.NewValue(replace); |
| 63 var f func(val reflect.Value) reflect.Value; // f is recursive |
| 64 f = func(val reflect.Value) reflect.Value { |
| 65 for k := range m { |
| 66 m[k] = nil, false |
| 67 } |
| 68 if match(m, pat, val) { |
| 69 return subst(m, repl) |
| 70 } |
| 71 return apply(f, val); |
| 72 }; |
| 73 return apply(f, reflect.NewValue(p)).Interface().(*ast.File); |
| 74 } |
| 75 |
| 76 |
| 77 var positionType = reflect.Typeof(token.Position{}) |
| 78 var zeroPosition = reflect.NewValue(token.Position{}) |
| 79 var identType = reflect.Typeof((*ast.Ident)(nil)) |
| 80 |
| 81 |
| 82 func isWildcard(s string) bool { |
| 83 rune, _ := utf8.DecodeRuneInString(s); |
| 84 return unicode.Is(unicode.Greek, rune) && unicode.IsLower(rune); |
| 85 } |
| 86 |
| 87 |
| 88 // apply replaces each AST field x in val with f(x), returning val. |
| 89 // To avoid extra conversions, f operates on the reflect.Value form. |
| 90 func apply(f func(reflect.Value) reflect.Value, val reflect.Value) reflect.Value
{ |
| 91 if val == nil { |
| 92 return nil |
| 93 } |
| 94 switch v := reflect.Indirect(val).(type) { |
| 95 case *reflect.SliceValue: |
| 96 for i := 0; i < v.Len(); i++ { |
| 97 e := v.Elem(i); |
| 98 e.SetValue(f(e)); |
| 99 } |
| 100 case *reflect.StructValue: |
| 101 for i := 0; i < v.NumField(); i++ { |
| 102 e := v.Field(i); |
| 103 e.SetValue(f(e)); |
| 104 } |
| 105 case *reflect.InterfaceValue: |
| 106 e := v.Elem(); |
| 107 v.SetValue(f(e)); |
| 108 } |
| 109 return val; |
| 110 } |
| 111 |
| 112 |
| 113 // match returns true if pattern matches val, |
| 114 // recording wildcard submatches in m. |
| 115 // If m == nil, match checks whether pattern == val. |
| 116 func match(m map[string]reflect.Value, pattern, val reflect.Value) bool { |
| 117 // Wildcard matches any expression. If it appears multiple |
| 118 // times in the pattern, it must match the same expression |
| 119 // each time. |
| 120 if m != nil && pattern.Type() == identType { |
| 121 name := pattern.Interface().(*ast.Ident).Value; |
| 122 if isWildcard(name) { |
| 123 if old, ok := m[name]; ok { |
| 124 return match(nil, old, val) |
| 125 } |
| 126 m[name] = val; |
| 127 return true; |
| 128 } |
| 129 } |
| 130 |
| 131 // Otherwise, the expressions must match recursively. |
| 132 if pattern == nil || val == nil { |
| 133 return pattern == nil && val == nil |
| 134 } |
| 135 if pattern.Type() != val.Type() { |
| 136 return false |
| 137 } |
| 138 |
| 139 // Token positions need not match. |
| 140 if pattern.Type() == positionType { |
| 141 return true |
| 142 } |
| 143 |
| 144 p := reflect.Indirect(pattern); |
| 145 v := reflect.Indirect(val); |
| 146 |
| 147 switch p := p.(type) { |
| 148 case *reflect.SliceValue: |
| 149 v := v.(*reflect.SliceValue); |
| 150 for i := 0; i < p.Len(); i++ { |
| 151 if !match(m, p.Elem(i), v.Elem(i)) { |
| 152 return false |
| 153 } |
| 154 } |
| 155 return true; |
| 156 |
| 157 case *reflect.StructValue: |
| 158 v := v.(*reflect.StructValue); |
| 159 for i := 0; i < p.NumField(); i++ { |
| 160 if !match(m, p.Field(i), v.Field(i)) { |
| 161 return false |
| 162 } |
| 163 } |
| 164 return true; |
| 165 |
| 166 case *reflect.InterfaceValue: |
| 167 v := v.(*reflect.InterfaceValue); |
| 168 return match(m, p.Elem(), v.Elem()); |
| 169 } |
| 170 |
| 171 // Handle token integers, etc. |
| 172 return p.Interface() == v.Interface(); |
| 173 } |
| 174 |
| 175 |
| 176 // subst returns a copy of pattern with values from m substituted in place of wi
ldcards. |
| 177 // if m == nil, subst returns a copy of pattern. |
| 178 // Either way, the returned value has no valid line number information. |
| 179 func subst(m map[string]reflect.Value, pattern reflect.Value) reflect.Value { |
| 180 if pattern == nil { |
| 181 return nil |
| 182 } |
| 183 |
| 184 // Wildcard gets replaced with map value. |
| 185 if m != nil && pattern.Type() == identType { |
| 186 name := pattern.Interface().(*ast.Ident).Value; |
| 187 if isWildcard(name) { |
| 188 if old, ok := m[name]; ok { |
| 189 return subst(nil, old) |
| 190 } |
| 191 } |
| 192 } |
| 193 |
| 194 if pattern.Type() == positionType { |
| 195 return zeroPosition |
| 196 } |
| 197 |
| 198 // Otherwise copy. |
| 199 switch p := pattern.(type) { |
| 200 case *reflect.SliceValue: |
| 201 v := reflect.MakeSlice(p.Type().(*reflect.SliceType), p.Len(), p
.Len()); |
| 202 for i := 0; i < p.Len(); i++ { |
| 203 v.Elem(i).SetValue(subst(m, p.Elem(i))) |
| 204 } |
| 205 return v; |
| 206 |
| 207 case *reflect.StructValue: |
| 208 v := reflect.MakeZero(p.Type()).(*reflect.StructValue); |
| 209 for i := 0; i < p.NumField(); i++ { |
| 210 v.Field(i).SetValue(subst(m, p.Field(i))) |
| 211 } |
| 212 return v; |
| 213 |
| 214 case *reflect.PtrValue: |
| 215 v := reflect.MakeZero(p.Type()).(*reflect.PtrValue); |
| 216 v.PointTo(subst(m, p.Elem())); |
| 217 return v; |
| 218 |
| 219 case *reflect.InterfaceValue: |
| 220 v := reflect.MakeZero(p.Type()).(*reflect.InterfaceValue); |
| 221 v.SetValue(subst(m, p.Elem())); |
| 222 return v; |
| 223 } |
| 224 |
| 225 return pattern; |
| 226 } |
OLD | NEW |