/* Compiler implementation of the D programming language * Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved * written by Walter Bright * http://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. * http://www.boost.org/LICENSE_1_0.txt * https://github.com/D-Programming-Language/dmd/blob/master/src/sapply.c */ #include "root/dsystem.h" #include "mars.h" #include "statement.h" #include "visitor.h" /************************************** * A Statement tree walker that will visit each Statement s in the tree, * in depth-first evaluation order, and call fp(s,param) on it. * fp() signals whether the walking continues with its return value: * Returns: * 0 continue * 1 done * It's a bit slower than using virtual functions, but more encapsulated and less brittle. * Creating an iterator for this would be much more complex. */ class PostorderStatementVisitor : public StoppableVisitor { public: StoppableVisitor *v; PostorderStatementVisitor(StoppableVisitor *v) : v(v) {} bool doCond(Statement *s) { if (!stop && s) s->accept(this); return stop; } bool applyTo(Statement *s) { s->accept(v); stop = v->stop; return true; } void visit(Statement *s) { applyTo(s); } void visit(PeelStatement *s) { doCond(s->s) || applyTo(s); } void visit(CompoundStatement *s) { for (size_t i = 0; i < s->statements->dim; i++) if (doCond((*s->statements)[i])) return; applyTo(s); } void visit(UnrolledLoopStatement *s) { for (size_t i = 0; i < s->statements->dim; i++) if (doCond((*s->statements)[i])) return; applyTo(s); } void visit(ScopeStatement *s) { doCond(s->statement) || applyTo(s); } void visit(WhileStatement *s) { doCond(s->_body) || applyTo(s); } void visit(DoStatement *s) { doCond(s->_body) || applyTo(s); } void visit(ForStatement *s) { doCond(s->_init) || doCond(s->_body) || applyTo(s); } void visit(ForeachStatement *s) { doCond(s->_body) || applyTo(s); } void visit(ForeachRangeStatement *s) { doCond(s->_body) || applyTo(s); } void visit(IfStatement *s) { doCond(s->ifbody) || doCond(s->elsebody) || applyTo(s); } void visit(PragmaStatement *s) { doCond(s->_body) || applyTo(s); } void visit(SwitchStatement *s) { doCond(s->_body) || applyTo(s); } void visit(CaseStatement *s) { doCond(s->statement) || applyTo(s); } void visit(DefaultStatement *s) { doCond(s->statement) || applyTo(s); } void visit(SynchronizedStatement *s) { doCond(s->_body) || applyTo(s); } void visit(WithStatement *s) { doCond(s->_body) || applyTo(s); } void visit(TryCatchStatement *s) { if (doCond(s->_body)) return; for (size_t i = 0; i < s->catches->dim; i++) if (doCond((*s->catches)[i]->handler)) return; applyTo(s); } void visit(TryFinallyStatement *s) { doCond(s->_body) || doCond(s->finalbody) || applyTo(s); } void visit(OnScopeStatement *s) { doCond(s->statement) || applyTo(s); } void visit(DebugStatement *s) { doCond(s->statement) || applyTo(s); } void visit(LabelStatement *s) { doCond(s->statement) || applyTo(s); } }; bool walkPostorder(Statement *s, StoppableVisitor *v) { PostorderStatementVisitor pv(v); s->accept(&pv); return v->stop; }