d: Merge upstream dmd, druntime 4ca4140e58, phobos 454dff14d.
[official-gcc.git] / gcc / d / dmd / apply.d
blob59ba9f5ecd65fb815c8bde7b5d2f0bc401d8b720
1 /**
2 * A depth-first visitor for expressions.
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/apply.d, _apply.d)
8 * Documentation: https://dlang.org/phobos/dmd_apply.html
9 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/apply.d
12 module dmd.apply;
14 import dmd.arraytypes;
15 import dmd.dsymbol;
16 import dmd.dsymbolsem;
17 import dmd.dtemplate;
18 import dmd.expression;
19 import dmd.root.array;
20 import dmd.visitor;
22 bool walkPostorder(Expression e, StoppableVisitor v)
24 scope PostorderExpressionVisitor pv = new PostorderExpressionVisitor(v);
25 e.accept(pv);
26 return v.stop;
29 /*********************************
30 * Iterate this dsymbol or members of this scoped dsymbol, then
31 * call `fp` with the found symbol and `params`.
32 * Params:
33 * symbol = the dsymbol or parent of members to call fp on
34 * fp = function pointer to process the iterated symbol.
35 * If it returns nonzero, the iteration will be aborted.
36 * params = any parameters passed to fp.
37 * Returns:
38 * nonzero if the iteration is aborted by the return value of fp,
39 * or 0 if it's completed.
41 int apply(FP, Params...)(Dsymbol symbol, FP fp, Params params)
43 if (auto nd = symbol.isNspace())
45 return nd.members.foreachDsymbol( (s) { return s && s.apply(fp, params); } );
47 if (auto ad = symbol.isAttribDeclaration())
49 return ad.include(ad._scope).foreachDsymbol( (s) { return s && s.apply(fp, params); } );
51 if (auto tm = symbol.isTemplateMixin())
53 if (tm._scope) // if fwd reference
54 dsymbolSemantic(tm, null); // try to resolve it
56 return tm.members.foreachDsymbol( (s) { return s && s.apply(fp, params); } );
59 return fp(symbol, params);
62 /**************************************
63 * An Expression tree walker that will visit each Expression e in the tree,
64 * in depth-first evaluation order, and call fp(e,param) on it.
65 * fp() signals whether the walking continues with its return value:
66 * Returns:
67 * 0 continue
68 * 1 done
69 * It's a bit slower than using virtual functions, but more encapsulated and less brittle.
70 * Creating an iterator for this would be much more complex.
72 private extern (C++) final class PostorderExpressionVisitor : StoppableVisitor
74 alias visit = typeof(super).visit;
75 public:
76 StoppableVisitor v;
78 extern (D) this(StoppableVisitor v) scope
80 this.v = v;
83 bool doCond(Expression e)
85 if (!stop && e)
86 e.accept(this);
87 return stop;
90 extern(D) bool doCond(Expression[] e)
92 for (size_t i = 0; i < e.length && !stop; i++)
93 doCond(e[i]);
94 return stop;
97 bool applyTo(Expression e)
99 e.accept(v);
100 stop = v.stop;
101 return true;
104 override void visit(Expression e)
106 applyTo(e);
109 override void visit(NewExp e)
111 //printf("NewExp::apply(): %s\n", toChars());
112 doCond(e.thisexp) || doCond(e.arguments.peekSlice()) || applyTo(e);
115 override void visit(NewAnonClassExp e)
117 //printf("NewAnonClassExp::apply(): %s\n", toChars());
118 doCond(e.thisexp) || doCond(e.arguments.peekSlice()) || applyTo(e);
121 override void visit(TypeidExp e)
123 doCond(isExpression(e.obj)) || applyTo(e);
126 override void visit(UnaExp e)
128 doCond(e.e1) || applyTo(e);
131 override void visit(BinExp e)
133 doCond(e.e1) || doCond(e.e2) || applyTo(e);
136 override void visit(AssertExp e)
138 //printf("CallExp::apply(apply_fp_t fp, void *param): %s\n", toChars());
139 doCond(e.e1) || doCond(e.msg) || applyTo(e);
142 override void visit(CallExp e)
144 //printf("CallExp::apply(apply_fp_t fp, void *param): %s\n", toChars());
145 doCond(e.e1) || doCond(e.arguments.peekSlice()) || applyTo(e);
148 override void visit(ArrayExp e)
150 //printf("ArrayExp::apply(apply_fp_t fp, void *param): %s\n", toChars());
151 doCond(e.e1) || doCond(e.arguments.peekSlice()) || applyTo(e);
154 override void visit(SliceExp e)
156 doCond(e.e1) || doCond(e.lwr) || doCond(e.upr) || applyTo(e);
159 override void visit(ArrayLiteralExp e)
161 doCond(e.basis) || doCond(e.elements.peekSlice()) || applyTo(e);
164 override void visit(AssocArrayLiteralExp e)
166 doCond(e.keys.peekSlice()) || doCond(e.values.peekSlice()) || applyTo(e);
169 override void visit(StructLiteralExp e)
171 if (e.stageflags & stageApply)
172 return;
173 int old = e.stageflags;
174 e.stageflags |= stageApply;
175 doCond(e.elements.peekSlice()) || applyTo(e);
176 e.stageflags = old;
179 override void visit(TupleExp e)
181 doCond(e.e0) || doCond(e.exps.peekSlice()) || applyTo(e);
184 override void visit(CondExp e)
186 doCond(e.econd) || doCond(e.e1) || doCond(e.e2) || applyTo(e);