github.com/mattn/anko@v0.1.10/ast/astutil/walk.go (about) 1 // +build !appengine 2 3 package astutil 4 5 import ( 6 "fmt" 7 "reflect" 8 9 "github.com/mattn/anko/ast" 10 ) 11 12 // WalkFunc is used in Walk to walk the AST 13 type WalkFunc func(interface{}) error 14 15 // Walk walks the ASTs associated with a statement list generated by parser.ParseSrc 16 // each expression and/or statement is passed to the WalkFunc function. 17 // If the WalkFunc returns an error the walk is aborted and the error is returned 18 func Walk(stmt ast.Stmt, f WalkFunc) error { 19 return walkStmt(stmt, f) 20 } 21 22 func walkStmts(stmts []ast.Stmt, f WalkFunc) error { 23 for _, stmt := range stmts { 24 if err := walkStmt(stmt, f); err != nil { 25 return err 26 } 27 } 28 return nil 29 } 30 31 func walkExprs(exprs []ast.Expr, f WalkFunc) error { 32 for _, exp := range exprs { 33 if err := walkExpr(exp, f); err != nil { 34 return err 35 } 36 } 37 return nil 38 } 39 40 func walkStmt(stmt ast.Stmt, f WalkFunc) error { 41 //short circuit out if there are no functions 42 if stmt == nil || f == nil { 43 return nil 44 } 45 if err := callFunc(stmt, f); err != nil { 46 return err 47 } 48 switch stmt := stmt.(type) { 49 case *ast.StmtsStmt: 50 if err := walkStmts(stmt.Stmts, f); err != nil { 51 return err 52 } 53 case *ast.BreakStmt: 54 case *ast.ContinueStmt: 55 case *ast.LetMapItemStmt: 56 if err := walkExpr(stmt.RHS, f); err != nil { 57 return err 58 } 59 return walkExprs(stmt.LHSS, f) 60 case *ast.ReturnStmt: 61 return walkExprs(stmt.Exprs, f) 62 case *ast.ExprStmt: 63 return walkExpr(stmt.Expr, f) 64 case *ast.VarStmt: 65 return walkExprs(stmt.Exprs, f) 66 case *ast.LetsStmt: 67 if err := walkExprs(stmt.RHSS, f); err != nil { 68 return err 69 } 70 return walkExprs(stmt.LHSS, f) 71 case *ast.IfStmt: 72 if err := walkExpr(stmt.If, f); err != nil { 73 return err 74 } 75 if err := walkStmt(stmt.Then, f); err != nil { 76 return err 77 } 78 if err := walkStmts(stmt.ElseIf, f); err != nil { 79 return err 80 } 81 if err := walkStmt(stmt.Else, f); err != nil { 82 return err 83 } 84 case *ast.TryStmt: 85 if err := walkStmt(stmt.Try, f); err != nil { 86 return err 87 } 88 if err := walkStmt(stmt.Catch, f); err != nil { 89 return err 90 } 91 if err := walkStmt(stmt.Finally, f); err != nil { 92 return err 93 } 94 case *ast.LoopStmt: 95 if err := walkExpr(stmt.Expr, f); err != nil { 96 return err 97 } 98 if err := walkStmt(stmt.Stmt, f); err != nil { 99 return err 100 } 101 case *ast.ForStmt: 102 if err := walkExpr(stmt.Value, f); err != nil { 103 return err 104 } 105 if err := walkStmt(stmt.Stmt, f); err != nil { 106 return err 107 } 108 case *ast.CForStmt: 109 if err := walkStmt(stmt.Stmt1, f); err != nil { 110 return err 111 } 112 if err := walkExpr(stmt.Expr2, f); err != nil { 113 return err 114 } 115 if err := walkExpr(stmt.Expr3, f); err != nil { 116 return err 117 } 118 if err := walkStmt(stmt.Stmt, f); err != nil { 119 return err 120 } 121 case *ast.ThrowStmt: 122 if err := walkExpr(stmt.Expr, f); err != nil { 123 return err 124 } 125 case *ast.ModuleStmt: 126 if err := walkStmt(stmt.Stmt, f); err != nil { 127 return err 128 } 129 case *ast.SwitchStmt: 130 if err := walkExpr(stmt.Expr, f); err != nil { 131 return err 132 } 133 for _, switchCaseStmt := range stmt.Cases { 134 caseStmt := switchCaseStmt.(*ast.SwitchCaseStmt) 135 if err := walkStmt(caseStmt.Stmt, f); err != nil { 136 return err 137 } 138 } 139 if err := walkStmt(stmt.Default, f); err != nil { 140 return err 141 } 142 case *ast.GoroutineStmt: 143 return walkExpr(stmt.Expr, f) 144 default: 145 return fmt.Errorf("unknown statement %v", reflect.TypeOf(stmt)) 146 } 147 return nil 148 } 149 150 func walkExpr(expr ast.Expr, f WalkFunc) error { 151 //short circuit out if there are no functions 152 if expr == nil || f == nil { 153 return nil 154 } 155 if err := callFunc(expr, f); err != nil { 156 return err 157 } 158 switch expr := expr.(type) { 159 case *ast.OpExpr: 160 return walkOperator(expr.Op, f) 161 case *ast.LenExpr: 162 case *ast.LiteralExpr: 163 case *ast.IdentExpr: 164 case *ast.MemberExpr: 165 return walkExpr(expr.Expr, f) 166 case *ast.ItemExpr: 167 if err := walkExpr(expr.Item, f); err != nil { 168 return err 169 } 170 return walkExpr(expr.Index, f) 171 case *ast.SliceExpr: 172 if err := walkExpr(expr.Item, f); err != nil { 173 return err 174 } 175 if err := walkExpr(expr.Begin, f); err != nil { 176 return err 177 } 178 return walkExpr(expr.End, f) 179 case *ast.ArrayExpr: 180 return walkExprs(expr.Exprs, f) 181 case *ast.MapExpr: 182 for i := range expr.Keys { 183 if err := walkExpr(expr.Keys[i], f); err != nil { 184 return err 185 } 186 if err := walkExpr(expr.Values[i], f); err != nil { 187 return err 188 } 189 } 190 case *ast.DerefExpr: 191 return walkExpr(expr.Expr, f) 192 case *ast.AddrExpr: 193 return walkExpr(expr.Expr, f) 194 case *ast.UnaryExpr: 195 return walkExpr(expr.Expr, f) 196 case *ast.ParenExpr: 197 return walkExpr(expr.SubExpr, f) 198 case *ast.FuncExpr: 199 return walkStmt(expr.Stmt, f) 200 case *ast.LetsExpr: 201 if err := walkExprs(expr.LHSS, f); err != nil { 202 return err 203 } 204 return walkExprs(expr.RHSS, f) 205 case *ast.AnonCallExpr: 206 if err := walkExpr(expr.Expr, f); err != nil { 207 return err 208 } 209 return walkExpr(&ast.CallExpr{Func: reflect.Value{}, SubExprs: expr.SubExprs, VarArg: expr.VarArg, Go: expr.Go}, f) 210 case *ast.CallExpr: 211 return walkExprs(expr.SubExprs, f) 212 case *ast.TernaryOpExpr: 213 if err := walkExpr(expr.Expr, f); err != nil { 214 return err 215 } 216 if err := walkExpr(expr.LHS, f); err != nil { 217 return err 218 } 219 return walkExpr(expr.RHS, f) 220 case *ast.ImportExpr: 221 return walkExpr(expr.Name, f) 222 case *ast.MakeExpr: 223 if err := walkExpr(expr.LenExpr, f); err != nil { 224 return err 225 } 226 return walkExpr(expr.CapExpr, f) 227 case *ast.ChanExpr: 228 if err := walkExpr(expr.RHS, f); err != nil { 229 return err 230 } 231 return walkExpr(expr.LHS, f) 232 case *ast.IncludeExpr: 233 if err := walkExpr(expr.ItemExpr, f); err != nil { 234 return err 235 } 236 return walkExpr(expr.ListExpr, f) 237 default: 238 return fmt.Errorf("unknown expression %v", reflect.TypeOf(expr)) 239 } 240 return nil 241 } 242 243 func walkOperator(op ast.Operator, f WalkFunc) error { 244 //short circuit out if there are no functions 245 if op == nil || f == nil { 246 return nil 247 } 248 if err := callFunc(op, f); err != nil { 249 return err 250 } 251 switch op := op.(type) { 252 case *ast.BinaryOperator: 253 if err := walkExpr(op.LHS, f); err != nil { 254 return err 255 } 256 return walkExpr(op.RHS, f) 257 case *ast.ComparisonOperator: 258 if err := walkExpr(op.LHS, f); err != nil { 259 return err 260 } 261 return walkExpr(op.RHS, f) 262 case *ast.AddOperator: 263 if err := walkExpr(op.LHS, f); err != nil { 264 return err 265 } 266 return walkExpr(op.RHS, f) 267 case *ast.MultiplyOperator: 268 if err := walkExpr(op.LHS, f); err != nil { 269 return err 270 } 271 return walkExpr(op.RHS, f) 272 } 273 return nil 274 } 275 276 func callFunc(x interface{}, f WalkFunc) error { 277 if x == nil || f == nil { 278 return nil 279 } 280 return f(x) 281 }