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