d: Merge dmd, druntime d8e3976a58, phobos 7a6e95688
[official-gcc.git] / gcc / d / dmd / postordervisitor.d
blobfe189d47e9466f6a64cbd1d40578dbf4751982c6
1 /**
2 * A depth-first visitor for expressions.
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/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.postordervisitor;
14 import dmd.arraytypes;
15 import dmd.dtemplate;
16 import dmd.expression;
17 import dmd.root.array;
18 import dmd.visitor;
20 bool walkPostorder(Expression e, StoppableVisitor v)
22 scope PostorderExpressionVisitor pv = new PostorderExpressionVisitor(v);
23 e.accept(pv);
24 return v.stop;
27 /**************************************
28 * An Expression tree walker that will visit each Expression e in the tree,
29 * in depth-first evaluation order, and call fp(e,param) on it.
30 * fp() signals whether the walking continues with its return value:
31 * Returns:
32 * 0 continue
33 * 1 done
34 * It's a bit slower than using virtual functions, but more encapsulated and less brittle.
35 * Creating an iterator for this would be much more complex.
37 private extern (C++) final class PostorderExpressionVisitor : StoppableVisitor
39 alias visit = typeof(super).visit;
40 public:
41 StoppableVisitor v;
43 extern (D) this(StoppableVisitor v) scope @safe
45 this.v = v;
48 bool doCond(Expression e)
50 if (!stop && e)
51 e.accept(this);
52 return stop;
55 extern(D) bool doCond(Expression[] e)
57 for (size_t i = 0; i < e.length && !stop; i++)
58 doCond(e[i]);
59 return stop;
62 bool applyTo(Expression e)
64 e.accept(v);
65 stop = v.stop;
66 return true;
69 override void visit(Expression e)
71 applyTo(e);
74 override void visit(NewExp e)
76 //printf("NewExp::apply(): %s\n", toChars());
77 doCond(e.thisexp) || doCond(e.arguments.peekSlice()) || applyTo(e);
80 override void visit(NewAnonClassExp e)
82 //printf("NewAnonClassExp::apply(): %s\n", toChars());
83 doCond(e.thisexp) || doCond(e.arguments.peekSlice()) || applyTo(e);
86 override void visit(TypeidExp e)
88 doCond(isExpression(e.obj)) || applyTo(e);
91 override void visit(UnaExp e)
93 doCond(e.e1) || applyTo(e);
96 override void visit(BinExp e)
98 doCond(e.e1) || doCond(e.e2) || applyTo(e);
101 override void visit(AssertExp e)
103 //printf("CallExp::apply(apply_fp_t fp, void *param): %s\n", toChars());
104 doCond(e.e1) || doCond(e.msg) || applyTo(e);
107 override void visit(CallExp e)
109 //printf("CallExp::apply(apply_fp_t fp, void *param): %s\n", toChars());
110 doCond(e.e1) || doCond(e.arguments.peekSlice()) || applyTo(e);
113 override void visit(ArrayExp e)
115 //printf("ArrayExp::apply(apply_fp_t fp, void *param): %s\n", toChars());
116 doCond(e.e1) || doCond(e.arguments.peekSlice()) || applyTo(e);
119 override void visit(SliceExp e)
121 doCond(e.e1) || doCond(e.lwr) || doCond(e.upr) || applyTo(e);
124 override void visit(ArrayLiteralExp e)
126 doCond(e.basis) || doCond(e.elements.peekSlice()) || applyTo(e);
129 override void visit(AssocArrayLiteralExp e)
131 doCond(e.keys.peekSlice()) || doCond(e.values.peekSlice()) || applyTo(e);
134 override void visit(StructLiteralExp e)
136 if (e.stageflags & stageApply)
137 return;
138 const old = e.stageflags;
139 e.stageflags |= stageApply;
140 doCond(e.elements.peekSlice()) || applyTo(e);
141 e.stageflags = old;
144 override void visit(TupleExp e)
146 doCond(e.e0) || doCond(e.exps.peekSlice()) || applyTo(e);
149 override void visit(CondExp e)
151 doCond(e.econd) || doCond(e.e1) || doCond(e.e2) || applyTo(e);