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