1 /**
2  * Compiler implementation of the
3  * $(LINK2 http://www.dlang.org, D programming language).
4  *
5  * Copyright:   Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved
6  * Authors:     $(LINK2 http://www.digitalmars.com, Walter Bright)
7  * License:     $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
8  * Source:      $(DMDSRC _apply.d)
9  */
10 
11 module ddmd.apply;
12 
13 import ddmd.arraytypes;
14 import ddmd.dtemplate;
15 import ddmd.expression;
16 import ddmd.visitor;
17 
18 /**************************************
19  * An Expression tree walker that will visit each Expression e in the tree,
20  * in depth-first evaluation order, and call fp(e,param) on it.
21  * fp() signals whether the walking continues with its return value:
22  * Returns:
23  *      0       continue
24  *      1       done
25  * It's a bit slower than using virtual functions, but more encapsulated and less brittle.
26  * Creating an iterator for this would be much more complex.
27  */
28 extern (C++) final class PostorderExpressionVisitor : StoppableVisitor
29 {
30     alias visit = super.visit;
31 public:
32     StoppableVisitor v;
33 
34     extern (D) this(StoppableVisitor v)
35     {
36         this.v = v;
37     }
38 
39     bool doCond(Expression e)
40     {
41         if (!stop && e)
42             e.accept(this);
43         return stop;
44     }
45 
46     bool doCond(Expressions* e)
47     {
48         if (!e)
49             return false;
50         for (size_t i = 0; i < e.dim && !stop; i++)
51             doCond((*e)[i]);
52         return stop;
53     }
54 
55     bool applyTo(Expression e)
56     {
57         e.accept(v);
58         stop = v.stop;
59         return true;
60     }
61 
62     override void visit(Expression e)
63     {
64         applyTo(e);
65     }
66 
67     override void visit(NewExp e)
68     {
69         //printf("NewExp::apply(): %s\n", toChars());
70         doCond(e.thisexp) || doCond(e.newargs) || doCond(e.arguments) || applyTo(e);
71     }
72 
73     override void visit(NewAnonClassExp e)
74     {
75         //printf("NewAnonClassExp::apply(): %s\n", toChars());
76         doCond(e.thisexp) || doCond(e.newargs) || doCond(e.arguments) || applyTo(e);
77     }
78 
79     override void visit(TypeidExp e)
80     {
81         doCond(isExpression(e.obj)) || applyTo(e);
82     }
83 
84     override void visit(UnaExp e)
85     {
86         doCond(e.e1) || applyTo(e);
87     }
88 
89     override void visit(BinExp e)
90     {
91         doCond(e.e1) || doCond(e.e2) || applyTo(e);
92     }
93 
94     override void visit(AssertExp e)
95     {
96         //printf("CallExp::apply(apply_fp_t fp, void *param): %s\n", toChars());
97         doCond(e.e1) || doCond(e.msg) || applyTo(e);
98     }
99 
100     override void visit(CallExp e)
101     {
102         //printf("CallExp::apply(apply_fp_t fp, void *param): %s\n", toChars());
103         doCond(e.e1) || doCond(e.arguments) || applyTo(e);
104     }
105 
106     override void visit(ArrayExp e)
107     {
108         //printf("ArrayExp::apply(apply_fp_t fp, void *param): %s\n", toChars());
109         doCond(e.e1) || doCond(e.arguments) || applyTo(e);
110     }
111 
112     override void visit(SliceExp e)
113     {
114         doCond(e.e1) || doCond(e.lwr) || doCond(e.upr) || applyTo(e);
115     }
116 
117     override void visit(ArrayLiteralExp e)
118     {
119         doCond(e.basis) || doCond(e.elements) || applyTo(e);
120     }
121 
122     override void visit(AssocArrayLiteralExp e)
123     {
124         doCond(e.keys) || doCond(e.values) || applyTo(e);
125     }
126 
127     override void visit(StructLiteralExp e)
128     {
129         if (e.stageflags & stageApply)
130             return;
131         int old = e.stageflags;
132         e.stageflags |= stageApply;
133         doCond(e.elements) || applyTo(e);
134         e.stageflags = old;
135     }
136 
137     override void visit(TupleExp e)
138     {
139         doCond(e.e0) || doCond(e.exps) || applyTo(e);
140     }
141 
142     override void visit(CondExp e)
143     {
144         doCond(e.econd) || doCond(e.e1) || doCond(e.e2) || applyTo(e);
145     }
146 }
147 
148 extern (C++) bool walkPostorder(Expression e, StoppableVisitor v)
149 {
150     scope PostorderExpressionVisitor pv = new PostorderExpressionVisitor(v);
151     e.accept(pv);
152     return v.stop;
153 }