1 /**
2  * Provides a visitor for statements that allows rewriting the currently visited node.
3  *
4  * Copyright:   Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved
5  * Authors:     $(LINK2 https://www.digitalmars.com, Walter Bright)
6  * License:     $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
7  * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/statement_rewrite_walker.d, _statement_rewrite_walker.d)
8  * Documentation:  https://dlang.org/phobos/dmd_statement_rewrite_walker.html
9  * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/statement_rewrite_walker.d
10  */
11 
12 module dmd.statement_rewrite_walker;
13 
14 import core.stdc.stdio;
15 
16 import dmd.statement;
17 import dmd.visitor;
18 
19 
20 /** A visitor to walk entire statements and provides ability to replace any sub-statements.
21  */
22 extern (C++) class StatementRewriteWalker : SemanticTimePermissiveVisitor
23 {
24     alias visit = SemanticTimePermissiveVisitor.visit;
25 
26     /* Point the currently visited statement.
27      * By using replaceCurrent() method, you can replace AST during walking.
28      */
29     Statement* ps;
30 
31 public:
32     final void visitStmt(ref Statement s)
33     {
34         ps = &s;
35         s.accept(this);
36     }
37 
38     final void replaceCurrent(Statement s)
39     {
40         *ps = s;
41     }
42 
43     override void visit(PeelStatement s)
44     {
45         if (s.s)
46             visitStmt(s.s);
47     }
48 
49     override void visit(CompoundStatement s)
50     {
51         if (s.statements && s.statements.length)
52         {
53             for (size_t i = 0; i < s.statements.length; i++)
54             {
55                 if ((*s.statements)[i])
56                     visitStmt((*s.statements)[i]);
57             }
58         }
59     }
60 
61     override void visit(CompoundDeclarationStatement s)
62     {
63         visit(cast(CompoundStatement)s);
64     }
65 
66     override void visit(UnrolledLoopStatement s)
67     {
68         if (s.statements && s.statements.length)
69         {
70             for (size_t i = 0; i < s.statements.length; i++)
71             {
72                 if ((*s.statements)[i])
73                     visitStmt((*s.statements)[i]);
74             }
75         }
76     }
77 
78     override void visit(ScopeStatement s)
79     {
80         if (s.statement)
81             visitStmt(s.statement);
82     }
83 
84     override void visit(WhileStatement s)
85     {
86         if (s._body)
87             visitStmt(s._body);
88     }
89 
90     override void visit(DoStatement s)
91     {
92         if (s._body)
93             visitStmt(s._body);
94     }
95 
96     override void visit(ForStatement s)
97     {
98         if (s._init)
99             visitStmt(s._init);
100         if (s._body)
101             visitStmt(s._body);
102     }
103 
104     override void visit(ForeachStatement s)
105     {
106         if (s._body)
107             visitStmt(s._body);
108     }
109 
110     override void visit(ForeachRangeStatement s)
111     {
112         if (s._body)
113             visitStmt(s._body);
114     }
115 
116     override void visit(IfStatement s)
117     {
118         if (s.ifbody)
119             visitStmt(s.ifbody);
120         if (s.elsebody)
121             visitStmt(s.elsebody);
122     }
123 
124     override void visit(SwitchStatement s)
125     {
126         if (s._body)
127             visitStmt(s._body);
128     }
129 
130     override void visit(CaseStatement s)
131     {
132         if (s.statement)
133             visitStmt(s.statement);
134     }
135 
136     override void visit(CaseRangeStatement s)
137     {
138         if (s.statement)
139             visitStmt(s.statement);
140     }
141 
142     override void visit(DefaultStatement s)
143     {
144         if (s.statement)
145             visitStmt(s.statement);
146     }
147 
148     override void visit(SynchronizedStatement s)
149     {
150         if (s._body)
151             visitStmt(s._body);
152     }
153 
154     override void visit(WithStatement s)
155     {
156         if (s._body)
157             visitStmt(s._body);
158     }
159 
160     override void visit(TryCatchStatement s)
161     {
162         if (s._body)
163             visitStmt(s._body);
164         if (s.catches && s.catches.length)
165         {
166             for (size_t i = 0; i < s.catches.length; i++)
167             {
168                 Catch c = (*s.catches)[i];
169                 if (c && c.handler)
170                     visitStmt(c.handler);
171             }
172         }
173     }
174 
175     override void visit(TryFinallyStatement s)
176     {
177         if (s._body)
178             visitStmt(s._body);
179         if (s.finalbody)
180             visitStmt(s.finalbody);
181     }
182 
183     override void visit(DebugStatement s)
184     {
185         if (s.statement)
186             visitStmt(s.statement);
187     }
188 
189     override void visit(LabelStatement s)
190     {
191         if (s.statement)
192             visitStmt(s.statement);
193     }
194 }