backpropAcrossNode is the main driver function for the backpropagation of each node of different types. For some complicated cases, it further delegates the handling to other finer-grained backpropX functions for better code clarity.
(rootNode *RootAssertionNode, node ast.Node)
| 61 | // different types. For some complicated cases, it further delegates the handling to other |
| 62 | // finer-grained backpropX functions for better code clarity. |
| 63 | func backpropAcrossNode(rootNode *RootAssertionNode, node ast.Node) error { |
| 64 | switch n := node.(type) { |
| 65 | case *ast.ParenExpr: |
| 66 | return backpropAcrossNode(rootNode, n.X) |
| 67 | case *ast.ReturnStmt: |
| 68 | return backpropAcrossReturn(rootNode, n) |
| 69 | case *ast.AssignStmt: |
| 70 | return backpropAcrossAssignment(rootNode, n.Lhs, n.Rhs) |
| 71 | case *ast.ValueSpec: |
| 72 | // These nodes represent declarations such as `var x, y : int = 4, 3` |
| 73 | if len(n.Names) > 0 && len(n.Values) > 0 { |
| 74 | err := backpropAcrossAssignment(rootNode, toExprSlice(n.Names), n.Values) |
| 75 | if err != nil { |
| 76 | return err |
| 77 | } |
| 78 | } |
| 79 | case *ast.SendStmt: |
| 80 | return backpropAcrossSend(rootNode, n) |
| 81 | case *ast.ExprStmt: |
| 82 | rootNode.AddComputation(n.X) |
| 83 | case *ast.GoStmt: |
| 84 | rootNode.AddComputation(n.Call) |
| 85 | case *ast.IncDecStmt: |
| 86 | rootNode.AddComputation(n.X) |
| 87 | |
| 88 | case *ast.SelectorExpr: |
| 89 | rootNode.AddComputation(n) |
| 90 | case *ast.BinaryExpr: |
| 91 | rootNode.AddComputation(n) |
| 92 | case *ast.CallExpr: |
| 93 | rootNode.AddComputation(n) |
| 94 | case *ast.UnaryExpr: |
| 95 | rootNode.AddComputation(n) |
| 96 | case *ast.StarExpr: |
| 97 | rootNode.AddComputation(n) |
| 98 | case *ast.IndexExpr: |
| 99 | rootNode.AddComputation(n) |
| 100 | case *ast.SliceExpr: |
| 101 | rootNode.AddComputation(n) |
| 102 | case *ast.TypeAssertExpr: |
| 103 | rootNode.AddComputation(n) |
| 104 | case *ast.CompositeLit: |
| 105 | for _, expr := range n.Elts { |
| 106 | rootNode.AddComputation(expr) |
| 107 | } |
| 108 | // The following cases are not interesting to our nilness analysis, or are currently |
| 109 | // unsupported, so we do nothing for them. |
| 110 | case *ast.BasicLit, *ast.Ident, *ast.EmptyStmt, *ast.DeferStmt: |
| 111 | // TODO: figure out what source code generates these cases - it's not obvious |
| 112 | // TODO: handle defers |
| 113 | default: |
| 114 | return fmt.Errorf("unrecognized AST node %T in CFG - add a case for it", n) |
| 115 | } |
| 116 | |
| 117 | return nil |
| 118 | } |
| 119 | |
| 120 | // backpropAcrossSend handles backpropagation for send statements. It is designed to be called from |
no test coverage detected