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
14 import dmd
.arraytypes
;
16 import dmd
.dsymbolsem
;
18 import dmd
.expression
;
19 import dmd
.root
.array
;
22 bool walkPostorder(Expression e
, StoppableVisitor v
)
24 scope PostorderExpressionVisitor pv
= new PostorderExpressionVisitor(v
);
29 /*********************************
30 * Iterate this dsymbol or members of this scoped dsymbol, then
31 * call `fp` with the found symbol and `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.
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:
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
;
78 extern (D
) this(StoppableVisitor v
) scope
83 bool doCond(Expression e
)
90 extern(D
) bool doCond(Expression
[] e
)
92 for (size_t i
= 0; i
< e
.length
&& !stop
; i
++)
97 bool applyTo(Expression e
)
104 override void visit(Expression 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
)
173 int old
= e
.stageflags
;
174 e
.stageflags |
= stageApply
;
175 doCond(e
.elements
.peekSlice()) ||
applyTo(e
);
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
);