diff --git a/src/sapply.c b/src/sapply.c index 5a267e3420fe..4f9760bf86a2 100644 --- a/src/sapply.c +++ b/src/sapply.c @@ -13,6 +13,7 @@ #include "mars.h" #include "statement.h" +#include "visitor.h" /************************************** @@ -26,181 +27,130 @@ * Creating an iterator for this would be much more complex. */ -typedef bool (*sapply_fp_t)(Statement *, void *); - -bool Statement::apply(sapply_fp_t fp, void *param) -{ - return (*fp)(this, param); -} - -/****************************** - * Perform apply() on an t if not null - */ -#define scondApply(t, fp, param) (t ? t->apply(fp, param) : false) - - - -bool PeelStatement::apply(sapply_fp_t fp, void *param) -{ - return s->apply(fp, param) || - (*fp)(this, param); -} - -bool CompoundStatement::apply(sapply_fp_t fp, void *param) +class PostorderStatementVisitor : public StoppableVisitor { - for (size_t i = 0; i < statements->dim; i++) - { Statement *s = (*statements)[i]; +public: + StoppableVisitor *v; + PostorderStatementVisitor(StoppableVisitor *v) : v(v) {} - bool r = scondApply(s, fp, param); - if (r) - return r; + bool doCond(Statement *s) + { + if (!stop && s) + s->accept(this); + return stop; } - return (*fp)(this, param); -} - -bool UnrolledLoopStatement::apply(sapply_fp_t fp, void *param) -{ - for (size_t i = 0; i < statements->dim; i++) - { Statement *s = (*statements)[i]; - - bool r = scondApply(s, fp, param); - if (r) - return r; + bool applyTo(Statement *s) + { + s->accept(v); + stop = v->stop; + return true; } - return (*fp)(this, param); -} - -bool ScopeStatement::apply(sapply_fp_t fp, void *param) -{ - return scondApply(statement, fp, param) || - (*fp)(this, param); -} - -bool WhileStatement::apply(sapply_fp_t fp, void *param) -{ - return scondApply(body, fp, param) || - (*fp)(this, param); -} - -bool DoStatement::apply(sapply_fp_t fp, void *param) -{ - return scondApply(body, fp, param) || - (*fp)(this, param); -} - -bool ForStatement::apply(sapply_fp_t fp, void *param) -{ - return scondApply(init, fp, param) || - scondApply(body, fp, param) || - (*fp)(this, param); -} - -bool ForeachStatement::apply(sapply_fp_t fp, void *param) -{ - return scondApply(body, fp, param) || - (*fp)(this, param); -} - -bool ForeachRangeStatement::apply(sapply_fp_t fp, void *param) -{ - return scondApply(body, fp, param) || - (*fp)(this, param); -} - -bool IfStatement::apply(sapply_fp_t fp, void *param) -{ - return scondApply(ifbody, fp, param) || - scondApply(elsebody, fp, param) || - (*fp)(this, param); -} - -bool ConditionalStatement::apply(sapply_fp_t fp, void *param) -{ - return scondApply(ifbody, fp, param) || - scondApply(elsebody, fp, param) || - (*fp)(this, param); -} - -bool PragmaStatement::apply(sapply_fp_t fp, void *param) -{ - return scondApply(body, fp, param) || - (*fp)(this, param); -} - -bool SwitchStatement::apply(sapply_fp_t fp, void *param) -{ - return scondApply(body, fp, param) || - (*fp)(this, param); -} - -bool CaseStatement::apply(sapply_fp_t fp, void *param) -{ - return scondApply(statement, fp, param) || - (*fp)(this, param); -} - -bool CaseRangeStatement::apply(sapply_fp_t fp, void *param) -{ - return scondApply(statement, fp, param) || - (*fp)(this, param); -} - -bool DefaultStatement::apply(sapply_fp_t fp, void *param) -{ - return scondApply(statement, fp, param) || - (*fp)(this, param); -} - -bool SynchronizedStatement::apply(sapply_fp_t fp, void *param) -{ - return scondApply(body, fp, param) || - (*fp)(this, param); -} - -bool WithStatement::apply(sapply_fp_t fp, void *param) -{ - return scondApply(body, fp, param) || - (*fp)(this, param); -} - -bool TryCatchStatement::apply(sapply_fp_t fp, void *param) -{ - bool r = scondApply(body, fp, param); - if (r) - return r; - for (size_t i = 0; i < catches->dim; i++) - { Catch *c = (*catches)[i]; - - r = scondApply(c->handler, fp, param); - if (r) - return r; + void visit(Statement *s) + { + applyTo(s); } - return (*fp)(this, param); -} - -bool TryFinallyStatement::apply(sapply_fp_t fp, void *param) -{ - return scondApply(body, fp, param) || - scondApply(finalbody, fp, param) || - (*fp)(this, param); -} - -bool OnScopeStatement::apply(sapply_fp_t fp, void *param) -{ - return scondApply(statement, fp, param) || - (*fp)(this, param); -} - -bool DebugStatement::apply(sapply_fp_t fp, void *param) -{ - return scondApply(statement, fp, param) || - (*fp)(this, param); -} + 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 LabelStatement::apply(sapply_fp_t fp, void *param) +bool walkPostorder(Statement *s, StoppableVisitor *v) { - return scondApply(statement, fp, param) || - (*fp)(this, param); + PostorderStatementVisitor pv(v); + s->accept(&pv); + return v->stop; } - diff --git a/src/statement.c b/src/statement.c index 447ac7e1655e..589ca33459e8 100644 --- a/src/statement.c +++ b/src/statement.c @@ -31,6 +31,8 @@ #include "attrib.h" #include "import.h" +bool walkPostorder(Statement *s, StoppableVisitor *v); + Identifier *fixupLabelName(Scope *sc, Identifier *ident) { unsigned flags = (sc->flags & SCOPEcontract); @@ -170,71 +172,58 @@ bool Statement::hasContinue() bool Statement::usesEH() { - struct UsesEH + class UsesEH : public StoppableVisitor { - static bool lambdaUsesEH(Statement *s, void *param) - { - return s->usesEHimpl(); - } + public: + void visit(Statement *s) {} + void visit(TryCatchStatement *s) { stop = true; } + void visit(TryFinallyStatement *s) { stop = true; } + void visit(OnScopeStatement *s) { stop = true; } + void visit(SynchronizedStatement *s) { stop = true; } }; UsesEH ueh; - return apply(&UsesEH::lambdaUsesEH, &ueh); + return walkPostorder(this, &ueh); } -bool Statement::usesEHimpl() { return false; } -bool TryCatchStatement::usesEHimpl() { return true; } -bool TryFinallyStatement::usesEHimpl() { return true; } -bool OnScopeStatement::usesEHimpl() { return true; } -bool SynchronizedStatement::usesEHimpl() { return true; } - /* ============================================== */ // true if statement 'comes from' somewhere else, like a goto bool Statement::comeFrom() { - struct ComeFrom + class ComeFrom : public StoppableVisitor { - static bool lambdaComeFrom(Statement *s, void *param) - { - return s->comeFromImpl(); - } + public: + void visit(Statement *s) {} + void visit(CaseStatement *s) { stop = true; } + void visit(DefaultStatement *s) { stop = true; } + void visit(LabelStatement *s) { stop = true; } + void visit(AsmStatement *s) { stop = true; } }; ComeFrom cf; - return apply(&ComeFrom::lambdaComeFrom, &cf); + return walkPostorder(this, &cf); } -bool Statement::comeFromImpl() { return false; } -bool CaseStatement::comeFromImpl() { return true; } -bool DefaultStatement::comeFromImpl() { return true; } -bool LabelStatement::comeFromImpl() { return true; } -bool AsmStatement::comeFromImpl() { return true; } - /* ============================================== */ // Return true if statement has executable code. bool Statement::hasCode() { - struct HasCode + class HasCode : public StoppableVisitor { - static bool lambdaHasCode(Statement *s, void *param) - { - return s->hasCodeImpl(); - } + public: + void visit(Statement *s) { stop = true; } + void visit(ExpStatement *s) { stop = s->exp != NULL; } + void visit(CompoundStatement *s) {} + void visit(ScopeStatement *s) {} + void visit(ImportStatement *s) {} }; HasCode hc; - return apply(&HasCode::lambdaHasCode, &hc); + return walkPostorder(this, &hc); } -bool Statement::hasCodeImpl() { return true; } -bool ExpStatement::hasCodeImpl() { return exp != NULL; } -bool CompoundStatement::hasCodeImpl() { return false; } -bool ScopeStatement::hasCodeImpl() { return false; } -bool ImportStatement::hasCodeImpl() { return false; } - - /* ============================================== */ /* Only valid after semantic analysis diff --git a/src/statement.h b/src/statement.h index 07f7075d6541..763046e9f0f9 100644 --- a/src/statement.h +++ b/src/statement.h @@ -55,8 +55,6 @@ struct CompiledCtfeFunction; enum TOK; -typedef bool (*sapply_fp_t)(Statement *, void *); - // Back end struct IRState; struct Blockx; @@ -107,16 +105,12 @@ class Statement : public RootObject virtual bool hasBreak(); virtual bool hasContinue(); bool usesEH(); - virtual bool usesEHimpl(); virtual int blockExit(bool mustNotThrow); bool comeFrom(); - virtual bool comeFromImpl(); bool hasCode(); - virtual bool hasCodeImpl(); virtual Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally); virtual Statements *flatten(Scope *sc); virtual Expression *interpret(InterState *istate); - virtual bool apply(sapply_fp_t fp, void *param); virtual void ctfeCompile(CompiledCtfeFunction *ccf); virtual Statement *last(); @@ -159,7 +153,6 @@ class PeelStatement : public Statement PeelStatement(Statement *s); Statement *semantic(Scope *sc); - bool apply(sapply_fp_t fp, void *param); void accept(Visitor *v) { v->visit(this); } }; @@ -177,7 +170,6 @@ class ExpStatement : public Statement Expression *interpret(InterState *istate); void ctfeCompile(CompiledCtfeFunction *ccf); int blockExit(bool mustNotThrow); - bool hasCodeImpl(); Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally); Expression *doInline(InlineDoState *ids); @@ -228,11 +220,9 @@ class CompoundStatement : public Statement void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Statement *semantic(Scope *sc); int blockExit(bool mustNotThrow); - bool hasCodeImpl(); Statements *flatten(Scope *sc); ReturnStatement *isReturnStatement(); Expression *interpret(InterState *istate); - bool apply(sapply_fp_t fp, void *param); void ctfeCompile(CompiledCtfeFunction *ccf); Statement *last(); @@ -268,7 +258,6 @@ class UnrolledLoopStatement : public Statement bool hasContinue(); int blockExit(bool mustNotThrow); Expression *interpret(InterState *istate); - bool apply(sapply_fp_t fp, void *param); void ctfeCompile(CompiledCtfeFunction *ccf); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -293,9 +282,7 @@ class ScopeStatement : public Statement bool hasBreak(); bool hasContinue(); int blockExit(bool mustNotThrow); - bool hasCodeImpl(); Expression *interpret(InterState *istate); - bool apply(sapply_fp_t fp, void *param); void ctfeCompile(CompiledCtfeFunction *ccf); Expression *doInline(InlineDoState *ids); @@ -318,7 +305,6 @@ class WhileStatement : public Statement bool hasContinue(); int blockExit(bool mustNotThrow); Expression *interpret(InterState *istate); - bool apply(sapply_fp_t fp, void *param); void ctfeCompile(CompiledCtfeFunction *ccf); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -340,7 +326,6 @@ class DoStatement : public Statement bool hasContinue(); int blockExit(bool mustNotThrow); Expression *interpret(InterState *istate); - bool apply(sapply_fp_t fp, void *param); void ctfeCompile(CompiledCtfeFunction *ccf); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -371,7 +356,6 @@ class ForStatement : public Statement bool hasContinue(); int blockExit(bool mustNotThrow); Expression *interpret(InterState *istate); - bool apply(sapply_fp_t fp, void *param); void ctfeCompile(CompiledCtfeFunction *ccf); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -407,7 +391,6 @@ class ForeachStatement : public Statement bool hasContinue(); int blockExit(bool mustNotThrow); Expression *interpret(InterState *istate); - bool apply(sapply_fp_t fp, void *param); void ctfeCompile(CompiledCtfeFunction *ccf); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -435,7 +418,6 @@ class ForeachRangeStatement : public Statement bool hasContinue(); int blockExit(bool mustNotThrow); Expression *interpret(InterState *istate); - bool apply(sapply_fp_t fp, void *param); void ctfeCompile(CompiledCtfeFunction *ccf); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -458,7 +440,6 @@ class IfStatement : public Statement Statement *syntaxCopy(); Statement *semantic(Scope *sc); Expression *interpret(InterState *istate); - bool apply(sapply_fp_t fp, void *param); void ctfeCompile(CompiledCtfeFunction *ccf); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); int blockExit(bool mustNotThrow); @@ -483,7 +464,6 @@ class ConditionalStatement : public Statement Statement *semantic(Scope *sc); Statements *flatten(Scope *sc); int blockExit(bool mustNotThrow); - bool apply(sapply_fp_t fp, void *param); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void accept(Visitor *v) { v->visit(this); } @@ -500,7 +480,6 @@ class PragmaStatement : public Statement Statement *syntaxCopy(); Statement *semantic(Scope *sc); int blockExit(bool mustNotThrow); - bool apply(sapply_fp_t fp, void *param); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -541,7 +520,6 @@ class SwitchStatement : public Statement bool hasBreak(); int blockExit(bool mustNotThrow); Expression *interpret(InterState *istate); - bool apply(sapply_fp_t fp, void *param); void ctfeCompile(CompiledCtfeFunction *ccf); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -564,9 +542,7 @@ class CaseStatement : public Statement Statement *semantic(Scope *sc); int compare(RootObject *obj); int blockExit(bool mustNotThrow); - bool comeFromImpl(); Expression *interpret(InterState *istate); - bool apply(sapply_fp_t fp, void *param); void ctfeCompile(CompiledCtfeFunction *ccf); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); CaseStatement *isCaseStatement() { return this; } @@ -587,7 +563,6 @@ class CaseRangeStatement : public Statement CaseRangeStatement(Loc loc, Expression *first, Expression *last, Statement *s); Statement *syntaxCopy(); Statement *semantic(Scope *sc); - bool apply(sapply_fp_t fp, void *param); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void accept(Visitor *v) { v->visit(this); } }; @@ -605,9 +580,7 @@ class DefaultStatement : public Statement Statement *syntaxCopy(); Statement *semantic(Scope *sc); int blockExit(bool mustNotThrow); - bool comeFromImpl(); Expression *interpret(InterState *istate); - bool apply(sapply_fp_t fp, void *param); void ctfeCompile(CompiledCtfeFunction *ccf); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); DefaultStatement *isDefaultStatement() { return this; } @@ -726,9 +699,7 @@ class SynchronizedStatement : public Statement Statement *semantic(Scope *sc); bool hasBreak(); bool hasContinue(); - bool usesEHimpl(); int blockExit(bool mustNotThrow); - bool apply(sapply_fp_t fp, void *param); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Statement *inlineScan(InlineScanState *iss); @@ -752,7 +723,6 @@ class WithStatement : public Statement void toCBuffer(OutBuffer *buf, HdrGenState *hgs); int blockExit(bool mustNotThrow); Expression *interpret(InterState *istate); - bool apply(sapply_fp_t fp, void *param); void ctfeCompile(CompiledCtfeFunction *ccf); Statement *inlineScan(InlineScanState *iss); @@ -770,10 +740,8 @@ class TryCatchStatement : public Statement Statement *syntaxCopy(); Statement *semantic(Scope *sc); bool hasBreak(); - bool usesEHimpl(); int blockExit(bool mustNotThrow); Expression *interpret(InterState *istate); - bool apply(sapply_fp_t fp, void *param); void ctfeCompile(CompiledCtfeFunction *ccf); Statement *inlineScan(InlineScanState *iss); @@ -813,10 +781,8 @@ class TryFinallyStatement : public Statement Statement *semantic(Scope *sc); bool hasBreak(); bool hasContinue(); - bool usesEHimpl(); int blockExit(bool mustNotThrow); Expression *interpret(InterState *istate); - bool apply(sapply_fp_t fp, void *param); void ctfeCompile(CompiledCtfeFunction *ccf); Statement *inlineScan(InlineScanState *iss); @@ -835,10 +801,8 @@ class OnScopeStatement : public Statement int blockExit(bool mustNotThrow); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Statement *semantic(Scope *sc); - bool usesEHimpl(); Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally); Expression *interpret(InterState *istate); - bool apply(sapply_fp_t fp, void *param); void ctfeCompile(CompiledCtfeFunction *ccf); void accept(Visitor *v) { v->visit(this); } @@ -873,7 +837,6 @@ class DebugStatement : public Statement Statement *syntaxCopy(); Statement *semantic(Scope *sc); Statements *flatten(Scope *sc); - bool apply(sapply_fp_t fp, void *param); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void accept(Visitor *v) { v->visit(this); } }; @@ -916,9 +879,7 @@ class LabelStatement : public Statement Statement *semantic(Scope *sc); Statements *flatten(Scope *sc); int blockExit(bool mustNotThrow); - bool comeFromImpl(); Expression *interpret(InterState *istate); - bool apply(sapply_fp_t fp, void *param); void ctfeCompile(CompiledCtfeFunction *ccf); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -953,7 +914,6 @@ class AsmStatement : public Statement Statement *syntaxCopy(); Statement *semantic(Scope *sc); int blockExit(bool mustNotThrow); - bool comeFromImpl(); Expression *interpret(InterState *istate); void ctfeCompile(CompiledCtfeFunction *ccf); @@ -974,7 +934,6 @@ class ImportStatement : public Statement Statement *syntaxCopy(); Statement *semantic(Scope *sc); int blockExit(bool mustNotThrow); - bool hasCodeImpl(); Expression *interpret(InterState *istate); void ctfeCompile(CompiledCtfeFunction *ccf); diff --git a/src/visitor.h b/src/visitor.h index 6a8bdb94cc5e..4f7bc236f085 100644 --- a/src/visitor.h +++ b/src/visitor.h @@ -538,4 +538,11 @@ class Visitor virtual void visit(ThrownExceptionExp *e) { visit((Expression *)e); } }; +class StoppableVisitor : public Visitor +{ +public: + bool stop; + StoppableVisitor() : stop(false) {} +}; + #endif /* DMD_VISITOR_H */