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