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