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