d: Merge dmd, druntime d8e3976a58, phobos 7a6e95688
[official-gcc.git] / gcc / d / dmd / foreachvar.d
blob53b3c041d1e844d23d516afe3a4b682ba34f1709
1 /**
2 * Utility to visit every variable in an expression.
4 * Copyright: Copyright (C) 1999-2024 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;
18 import dmd.arraytypes;
19 import dmd.astenums;
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.postordervisitor;
36 import dmd.printast;
37 import dmd.root.array;
38 import dmd.rootobject;
39 import dmd.statement;
40 import dmd.tokens;
41 import dmd.visitor;
43 /*********************************************
44 * Visit each Expression in e, and call dgVar() on each variable declared in it.
45 * Params:
46 * e = expression tree to visit
47 * dgVar = call when a variable is declared
49 void foreachVar(Expression e, void delegate(VarDeclaration) dgVar)
51 if (!e)
52 return;
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 @safe
61 this.dgVar = dgVar;
64 override void visit(Expression e)
68 override void visit(ErrorExp e)
72 override void visit(DeclarationExp e)
74 VarDeclaration v = e.declaration.isVarDeclaration();
75 if (!v)
76 return;
77 if (TupleDeclaration td = v.toAlias().isTupleDeclaration())
78 td.foreachVar((s) { dgVar(s.isVarDeclaration()); });
79 else
80 dgVar(v);
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)
91 if (e.lengthVar)
92 dgVar(e.lengthVar);
95 override void visit(SliceExp e)
97 if (e.lengthVar)
98 dgVar(e.lengthVar);
102 scope VarWalker v = new VarWalker(dgVar);
103 walkPostorder(e, v);
106 /***************
107 * Transitively walk Statement s, pass Expressions to dgExp(), VarDeclarations to dgVar().
108 * Params:
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)
121 if (s.exp)
122 dgExp(s.exp);
125 void visitDtorExp(DtorExpStatement s)
127 if (s.exp)
128 dgExp(s.exp);
131 void visitIf(IfStatement s)
133 dgExp(s.condition);
134 visit(s.ifbody);
135 visit(s.elsebody);
138 void visitDo(DoStatement s)
140 dgExp(s.condition);
141 visit(s._body);
144 void visitFor(ForStatement s)
146 visit(s._init);
147 if (s.condition)
148 dgExp(s.condition);
149 if (s.increment)
150 dgExp(s.increment);
151 visit(s._body);
154 void visitSwitch(SwitchStatement s)
156 dgExp(s.condition);
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)
161 dgExp(cs.exp);
163 visit(s._body);
166 void visitCase(CaseStatement s)
168 visit(s.statement);
171 void visitReturn(ReturnStatement s)
173 if (s.exp)
174 dgExp(s.exp);
177 void visitCompound(CompoundStatement s)
179 if (s.statements)
181 foreach (s2; *s.statements)
183 visit(s2);
188 void visitCompoundDeclaration(CompoundDeclarationStatement s)
190 visitCompound(s);
193 void visitUnrolledLoop(UnrolledLoopStatement s)
195 foreach (s2; *s.statements)
197 visit(s2);
201 void visitScope(ScopeStatement s)
203 visit(s.statement);
206 void visitDefault(DefaultStatement s)
208 visit(s.statement);
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)
217 else
219 dgVar(s.wthis);
220 dgExp(s.exp);
222 visit(s._body);
225 void visitTryCatch(TryCatchStatement s)
227 visit(s._body);
228 foreach (ca; *s.catches)
230 if (ca.var)
231 dgVar(ca.var);
232 visit(ca.handler);
236 void visitTryFinally(TryFinallyStatement s)
238 visit(s._body);
239 visit(s.finalbody);
242 void visitThrow(ThrowStatement s)
244 dgExp(s.exp);
247 void visitLabel(LabelStatement s)
249 visit(s.statement);
252 if (!s)
253 return;
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:
277 case STMT.Asm:
278 case STMT.InlineAsm:
279 case STMT.GccAsm:
281 case STMT.Break:
282 case STMT.Continue:
283 case STMT.GotoDefault:
284 case STMT.GotoCase:
285 case STMT.SwitchError:
286 case STMT.Goto:
287 case STMT.Pragma:
288 case STMT.Import:
289 case STMT.Error:
290 break; // ignore these
292 case STMT.ScopeGuard:
293 case STMT.Foreach:
294 case STMT.ForeachRange:
295 case STMT.Debug:
296 case STMT.CaseRange:
297 case STMT.StaticForeach:
298 case STMT.StaticAssert:
299 case STMT.Conditional:
300 case STMT.While:
301 case STMT.Forwarding:
302 case STMT.Mixin:
303 case STMT.Peel:
304 case STMT.Synchronized:
305 assert(0); // should have been rewritten
309 visit(s);