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