2 * Utility to visit every variable in an expression.
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/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
12 module dmd
.foreachvar
;
14 import core
.stdc
.stdio
;
15 import core
.stdc
.stdlib
;
16 import core
.stdc
.string
;
19 import dmd
.arraytypes
;
23 import dmd
.declaration
;
26 import dmd
.dsymbolsem
;
29 import dmd
.expression
;
32 import dmd
.identifier
;
37 import dmd
.root
.array
;
38 import dmd
.root
.rootobject
;
43 /*********************************************
44 * Visit each Expression in e, and call dgVar() on each variable declared in it.
46 * e = expression tree to visit
47 * dgVar = call when a variable is declared
49 void foreachVar(Expression e
, void delegate(VarDeclaration
) dgVar
)
54 extern (C
++) final class VarWalker
: StoppableVisitor
56 alias visit
= typeof(super).visit
;
57 extern (D
) void delegate(VarDeclaration
) dgVar
;
59 extern (D
) this(void delegate(VarDeclaration
) dgVar
) scope
64 override void visit(Expression e
)
68 override void visit(ErrorExp e
)
72 override void visit(DeclarationExp e
)
74 VarDeclaration v
= e
.declaration
.isVarDeclaration();
77 if (TupleDeclaration td
= v
.toAlias().isTupleDeclaration())
78 td
.foreachVar((s
) { dgVar(s
.isVarDeclaration()); });
81 Dsymbol s
= v
.toAlias();
82 if (s
== v
&& !v
.isStatic() && v
._init
)
84 if (auto ie
= v
._init
.isExpInitializer())
85 ie
.exp
.foreachVar(dgVar
);
89 override void visit(IndexExp e
)
95 override void visit(SliceExp e
)
102 scope VarWalker v
= new VarWalker(dgVar
);
107 * Transitively walk Statement s, pass Expressions to dgExp(), VarDeclarations to dgVar().
109 * s = Statement to traverse
110 * dgExp = delegate to pass found Expressions to
111 * dgVar = delegate to pass found VarDeclarations to
113 void foreachExpAndVar(Statement s
,
114 void delegate(Expression
) dgExp
,
115 void delegate(VarDeclaration
) dgVar
)
117 void visit(Statement s
)
119 void visitExp(ExpStatement s
)
125 void visitDtorExp(DtorExpStatement s
)
131 void visitIf(IfStatement s
)
138 void visitDo(DoStatement s
)
144 void visitFor(ForStatement s
)
154 void visitSwitch(SwitchStatement s
)
157 // Note that the body contains the Case and Default
158 // statements, so we only need to compile the expressions
159 foreach (cs
; *s
.cases
)
166 void visitCase(CaseStatement s
)
171 void visitReturn(ReturnStatement s
)
177 void visitCompound(CompoundStatement s
)
181 foreach (s2
; *s
.statements
)
188 void visitCompoundDeclaration(CompoundDeclarationStatement s
)
193 void visitUnrolledLoop(UnrolledLoopStatement s
)
195 foreach (s2
; *s
.statements
)
201 void visitScope(ScopeStatement s
)
206 void visitDefault(DefaultStatement s
)
211 void visitWith(WithStatement s
)
213 // If it is with(Enum) {...}, just execute the body.
214 if (s
.exp
.op
== EXP
.scope_ || s
.exp
.op
== EXP
.type
)
225 void visitTryCatch(TryCatchStatement s
)
228 foreach (ca
; *s
.catches
)
236 void visitTryFinally(TryFinallyStatement s
)
242 void visitThrow(ThrowStatement s
)
247 void visitLabel(LabelStatement s
)
255 final switch (s
.stmt
)
257 case STMT
.Exp
: visitExp(s
.isExpStatement()); break;
258 case STMT
.DtorExp
: visitDtorExp(s
.isDtorExpStatement()); break;
259 case STMT
.Compound
: visitCompound(s
.isCompoundStatement()); break;
260 case STMT
.CompoundDeclaration
: visitCompoundDeclaration(s
.isCompoundDeclarationStatement()); break;
261 case STMT
.UnrolledLoop
: visitUnrolledLoop(s
.isUnrolledLoopStatement()); break;
262 case STMT
.Scope
: visitScope(s
.isScopeStatement()); break;
263 case STMT
.Do
: visitDo(s
.isDoStatement()); break;
264 case STMT
.For
: visitFor(s
.isForStatement()); break;
265 case STMT
.If
: visitIf(s
.isIfStatement()); break;
266 case STMT
.Switch
: visitSwitch(s
.isSwitchStatement()); break;
267 case STMT
.Case
: visitCase(s
.isCaseStatement()); break;
268 case STMT
.Default
: visitDefault(s
.isDefaultStatement()); break;
269 case STMT
.Return
: visitReturn(s
.isReturnStatement()); break;
270 case STMT
.With
: visitWith(s
.isWithStatement()); break;
271 case STMT
.TryCatch
: visitTryCatch(s
.isTryCatchStatement()); break;
272 case STMT
.TryFinally
: visitTryFinally(s
.isTryFinallyStatement()); break;
273 case STMT
.Throw
: visitThrow(s
.isThrowStatement()); break;
274 case STMT
.Label
: visitLabel(s
.isLabelStatement()); break;
276 case STMT
.CompoundAsm
:
283 case STMT
.GotoDefault
:
285 case STMT
.SwitchError
:
290 break; // ignore these
292 case STMT
.ScopeGuard
:
294 case STMT
.ForeachRange
:
297 case STMT
.StaticForeach
:
298 case STMT
.StaticAssert
:
299 case STMT
.Conditional
:
301 case STMT
.Forwarding
:
304 case STMT
.Synchronized
:
305 assert(0); // should have been rewritten