1
/**
2
 * Utility to visit every variable in an expression.
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/foreachvar.d, _foreachvar.d)
8
 * Documentation:  https://dlang.org/phobos/dmd_foreachvar.html
9
 * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/foreachvar.d
10
 */
11

12
module dmd.foreachvar;
13

14
import core.stdc.stdio;
15
import core.stdc.stdlib;
16
import core.stdc.string;
17

18
import dmd.apply;
19
import dmd.arraytypes;
20
import dmd.attrib;
21
import dmd.dclass;
22
import dmd.declaration;
23
import dmd.dstruct;
24
import dmd.dsymbol;
25
import dmd.dsymbolsem;
26
import dmd.dtemplate;
27
import dmd.errors;
28
import dmd.expression;
29
import dmd.func;
30
import dmd.id;
31
import dmd.identifier;
32
import dmd.init;
33
import dmd.initsem;
34
import dmd.mtype;
35
import dmd.printast;
36
import dmd.root.array;
37
import dmd.root.rootobject;
38
import dmd.statement;
39
import dmd.tokens;
40
import dmd.visitor;
41

42
/*********************************************
43
 * Visit each Expression in e, and call dgVar() on each variable declared in it.
44
 * Params:
45
 *      e = expression tree to visit
46
 *      dgVar = call when a variable is declared
47
 */
48
void foreachVar(Expression e, void delegate(VarDeclaration) dgVar)
49
{
50 1
    if (!e)
51 0
        return;
52

53
    extern (C++) final class VarWalker : StoppableVisitor
54
    {
55
        alias visit = typeof(super).visit;
56
        extern (D) void delegate(VarDeclaration) dgVar;
57

58 1
        extern (D) this(void delegate(VarDeclaration) dgVar)
59
        {
60 1
            this.dgVar = dgVar;
61
        }
62

63
        override void visit(Expression e)
64
        {
65
        }
66

67
        override void visit(ErrorExp e)
68
        {
69
        }
70

71
        override void visit(DeclarationExp e)
72
        {
73 1
            VarDeclaration v = e.declaration.isVarDeclaration();
74 1
            if (!v)
75 0
                return;
76 1
            if (TupleDeclaration td = v.toAlias().isTupleDeclaration())
77
            {
78 0
                if (!td.objects)
79 0
                    return;
80 0
                foreach (o; *td.objects)
81
                {
82 0
                    Expression ex = isExpression(o);
83 0
                    DsymbolExp s = ex ? ex.isDsymbolExp() : null;
84 0
                    assert(s);
85 0
                    VarDeclaration v2 = s.s.isVarDeclaration();
86 0
                    assert(v2);
87 0
                    dgVar(v2);
88
                }
89
            }
90
            else
91 1
                dgVar(v);
92 1
            Dsymbol s = v.toAlias();
93 1
            if (s == v && !v.isStatic() && v._init)
94
            {
95 1
                if (auto ie = v._init.isExpInitializer())
96 1
                    ie.exp.foreachVar(dgVar);
97
            }
98
        }
99

100
        override void visit(IndexExp e)
101
        {
102 0
            if (e.lengthVar)
103 0
                dgVar(e.lengthVar);
104
        }
105

106
        override void visit(SliceExp e)
107
        {
108 0
            if (e.lengthVar)
109 0
                dgVar(e.lengthVar);
110
        }
111
    }
112

113 1
    scope VarWalker v = new VarWalker(dgVar);
114 1
    walkPostorder(e, v);
115
}
116

117
/***************
118
 * Transitively walk Statement s, pass Expressions to dgExp(), VarDeclarations to dgVar().
119
 * Params:
120
 *      s = Statement to traverse
121
 *      dgExp = delegate to pass found Expressions to
122
 *      dgVar = delegate to pass found VarDeclarations to
123
 */
124
void foreachExpAndVar(Statement s,
125
        void delegate(Expression) dgExp,
126
        void delegate(VarDeclaration) dgVar)
127
{
128
    void visit(Statement s)
129
    {
130
        void visitExp(ExpStatement s)
131
        {
132 1
            if (s.exp)
133 1
                dgExp(s.exp);
134
        }
135

136
        void visitDtorExp(DtorExpStatement s)
137
        {
138 0
            if (s.exp)
139 0
                dgExp(s.exp);
140
        }
141

142
        void visitIf(IfStatement s)
143
        {
144 1
            dgExp(s.condition);
145 1
            visit(s.ifbody);
146 1
            visit(s.elsebody);
147
        }
148

149
        void visitDo(DoStatement s)
150
        {
151 0
            dgExp(s.condition);
152 0
            visit(s._body);
153
        }
154

155
        void visitFor(ForStatement s)
156
        {
157 1
            visit(s._init);
158 1
            if (s.condition)
159 1
                dgExp(s.condition);
160 1
            if (s.increment)
161 1
                dgExp(s.increment);
162 1
            visit(s._body);
163
        }
164

165
        void visitSwitch(SwitchStatement s)
166
        {
167 0
            dgExp(s.condition);
168
            // Note that the body contains the Case and Default
169
            // statements, so we only need to compile the expressions
170 0
            foreach (cs; *s.cases)
171
            {
172 0
                dgExp(cs.exp);
173
            }
174 0
            visit(s._body);
175
        }
176

177
        void visitCase(CaseStatement s)
178
        {
179 0
            visit(s.statement);
180
        }
181

182
        void visitReturn(ReturnStatement s)
183
        {
184 1
            if (s.exp)
185 1
                dgExp(s.exp);
186
        }
187

188
        void visitCompound(CompoundStatement s)
189
        {
190 1
            if (s.statements)
191
            {
192 1
                foreach (s2; *s.statements)
193
                {
194 1
                    visit(s2);
195
                }
196
            }
197
        }
198

199
        void visitCompoundDeclaration(CompoundDeclarationStatement s)
200
        {
201 0
            visitCompound(s);
202
        }
203

204
        void visitUnrolledLoop(UnrolledLoopStatement s)
205
        {
206 0
            foreach (s2; *s.statements)
207
            {
208 0
                visit(s2);
209
            }
210
        }
211

212
        void visitScope(ScopeStatement s)
213
        {
214 1
            visit(s.statement);
215
        }
216

217
        void visitDefault(DefaultStatement s)
218
        {
219 0
            visit(s.statement);
220
        }
221

222
        void visitWith(WithStatement s)
223
        {
224
            // If it is with(Enum) {...}, just execute the body.
225 0
            if (s.exp.op == TOK.scope_ || s.exp.op == TOK.type)
226
            {
227
            }
228
            else
229
            {
230 0
                dgVar(s.wthis);
231 0
                dgExp(s.exp);
232
            }
233 0
            visit(s._body);
234
        }
235

236
        void visitTryCatch(TryCatchStatement s)
237
        {
238 0
            visit(s._body);
239 0
            foreach (ca; *s.catches)
240
            {
241 0
                if (ca.var)
242 0
                    dgVar(ca.var);
243 0
                visit(ca.handler);
244
            }
245
        }
246

247
        void visitTryFinally(TryFinallyStatement s)
248
        {
249 0
            visit(s._body);
250 0
            visit(s.finalbody);
251
        }
252

253
        void visitThrow(ThrowStatement s)
254
        {
255 1
            dgExp(s.exp);
256
        }
257

258
        void visitLabel(LabelStatement s)
259
        {
260 0
            visit(s.statement);
261
        }
262

263 1
        if (!s)
264 1
            return;
265

266 1
        final switch (s.stmt)
267
        {
268 1
            case STMT.Exp:                 visitExp(s.isExpStatement()); break;
269 0
            case STMT.DtorExp:             visitDtorExp(s.isDtorExpStatement()); break;
270 1
            case STMT.Compound:            visitCompound(s.isCompoundStatement()); break;
271 0
            case STMT.CompoundDeclaration: visitCompoundDeclaration(s.isCompoundDeclarationStatement()); break;
272 0
            case STMT.UnrolledLoop:        visitUnrolledLoop(s.isUnrolledLoopStatement()); break;
273 1
            case STMT.Scope:               visitScope(s.isScopeStatement()); break;
274 0
            case STMT.Do:                  visitDo(s.isDoStatement()); break;
275 1
            case STMT.For:                 visitFor(s.isForStatement()); break;
276 1
            case STMT.If:                  visitIf(s.isIfStatement()); break;
277 0
            case STMT.Switch:              visitSwitch(s.isSwitchStatement()); break;
278 0
            case STMT.Case:                visitCase(s.isCaseStatement()); break;
279 0
            case STMT.Default:             visitDefault(s.isDefaultStatement()); break;
280 1
            case STMT.Return:              visitReturn(s.isReturnStatement()); break;
281 0
            case STMT.With:                visitWith(s.isWithStatement()); break;
282 0
            case STMT.TryCatch:            visitTryCatch(s.isTryCatchStatement()); break;
283 0
            case STMT.TryFinally:          visitTryFinally(s.isTryFinallyStatement()); break;
284 1
            case STMT.Throw:               visitThrow(s.isThrowStatement()); break;
285 0
            case STMT.Label:               visitLabel(s.isLabelStatement()); break;
286

287 0
            case STMT.CompoundAsm:
288 0
            case STMT.Asm:
289 0
            case STMT.InlineAsm:
290 0
            case STMT.GccAsm:
291

292 0
            case STMT.Break:
293 0
            case STMT.Continue:
294 0
            case STMT.GotoDefault:
295 0
            case STMT.GotoCase:
296 0
            case STMT.SwitchError:
297 0
            case STMT.Goto:
298 0
            case STMT.Pragma:
299 0
            case STMT.Import:
300 0
            case STMT.Error:
301 0
                break;          // ignore these
302

303 0
            case STMT.ScopeGuard:
304 0
            case STMT.Foreach:
305 0
            case STMT.ForeachRange:
306 0
            case STMT.Debug:
307 0
            case STMT.CaseRange:
308 0
            case STMT.StaticForeach:
309 0
            case STMT.StaticAssert:
310 0
            case STMT.Conditional:
311 0
            case STMT.While:
312 0
            case STMT.Forwarding:
313 0
            case STMT.Compile:
314 0
            case STMT.Peel:
315 0
            case STMT.Synchronized:
316 0
                assert(0);              // should have been rewritten
317
        }
318
    }
319

320 1
    visit(s);
321
}
322

Read our documentation on viewing source code .

Loading