1 /** 2 * Provides a depth-first statement visitor. 3 * 4 * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved 5 * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright) 6 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 7 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/sparse.d, _sparse.d) 8 * Documentation: https://dlang.org/phobos/dmd_sapply.html 9 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/sapply.d 10 */ 11 12 module dmd.sapply; 13 14 import dmd.statement; 15 import dmd.visitor; 16 17 /************************************** 18 * A Statement tree walker that will visit each Statement s in the tree, 19 * in depth-first evaluation order, and call fp(s,param) on it. 20 * fp() signals whether the walking continues with its return value: 21 * Returns: 22 * 0 continue 23 * 1 done 24 * It's a bit slower than using virtual functions, but more encapsulated and less brittle. 25 * Creating an iterator for this would be much more complex. 26 */ 27 extern (C++) final class PostorderStatementVisitor : StoppableVisitor 28 { 29 alias visit = typeof(super).visit; 30 public: 31 StoppableVisitor v; 32 33 extern (D) this(StoppableVisitor v) 34 { 35 this.v = v; 36 } 37 38 bool doCond(Statement s) 39 { 40 if (!stop && s) 41 s.accept(this); 42 return stop; 43 } 44 45 bool applyTo(Statement s) 46 { 47 s.accept(v); 48 stop = v.stop; 49 return true; 50 } 51 52 override void visit(Statement s) 53 { 54 applyTo(s); 55 } 56 57 override void visit(PeelStatement s) 58 { 59 doCond(s.s) || applyTo(s); 60 } 61 62 override void visit(CompoundStatement s) 63 { 64 for (size_t i = 0; i < s.statements.dim; i++) 65 if (doCond((*s.statements)[i])) 66 return; 67 applyTo(s); 68 } 69 70 override void visit(UnrolledLoopStatement s) 71 { 72 for (size_t i = 0; i < s.statements.dim; i++) 73 if (doCond((*s.statements)[i])) 74 return; 75 applyTo(s); 76 } 77 78 override void visit(ScopeStatement s) 79 { 80 doCond(s.statement) || applyTo(s); 81 } 82 83 override void visit(WhileStatement s) 84 { 85 doCond(s._body) || applyTo(s); 86 } 87 88 override void visit(DoStatement s) 89 { 90 doCond(s._body) || applyTo(s); 91 } 92 93 override void visit(ForStatement s) 94 { 95 doCond(s._init) || doCond(s._body) || applyTo(s); 96 } 97 98 override void visit(ForeachStatement s) 99 { 100 doCond(s._body) || applyTo(s); 101 } 102 103 override void visit(ForeachRangeStatement s) 104 { 105 doCond(s._body) || applyTo(s); 106 } 107 108 override void visit(IfStatement s) 109 { 110 doCond(s.ifbody) || doCond(s.elsebody) || applyTo(s); 111 } 112 113 override void visit(PragmaStatement s) 114 { 115 doCond(s._body) || applyTo(s); 116 } 117 118 override void visit(SwitchStatement s) 119 { 120 doCond(s._body) || applyTo(s); 121 } 122 123 override void visit(CaseStatement s) 124 { 125 doCond(s.statement) || applyTo(s); 126 } 127 128 override void visit(DefaultStatement s) 129 { 130 doCond(s.statement) || applyTo(s); 131 } 132 133 override void visit(SynchronizedStatement s) 134 { 135 doCond(s._body) || applyTo(s); 136 } 137 138 override void visit(WithStatement s) 139 { 140 doCond(s._body) || applyTo(s); 141 } 142 143 override void visit(TryCatchStatement s) 144 { 145 if (doCond(s._body)) 146 return; 147 for (size_t i = 0; i < s.catches.dim; i++) 148 if (doCond((*s.catches)[i].handler)) 149 return; 150 applyTo(s); 151 } 152 153 override void visit(TryFinallyStatement s) 154 { 155 doCond(s._body) || doCond(s.finalbody) || applyTo(s); 156 } 157 158 override void visit(ScopeGuardStatement s) 159 { 160 doCond(s.statement) || applyTo(s); 161 } 162 163 override void visit(DebugStatement s) 164 { 165 doCond(s.statement) || applyTo(s); 166 } 167 168 override void visit(LabelStatement s) 169 { 170 doCond(s.statement) || applyTo(s); 171 } 172 } 173 174 bool walkPostorder(Statement s, StoppableVisitor v) 175 { 176 scope PostorderStatementVisitor pv = new PostorderStatementVisitor(v); 177 s.accept(pv); 178 return v.stop; 179 }