xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/d/dmd/sapply.c (revision 2f62cc9c12bc202c40224f32c879f81443fee079)
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/sapply.c
9  */
10 
11 #include "root/dsystem.h"
12 
13 #include "mars.h"
14 #include "statement.h"
15 #include "visitor.h"
16 
17 
18 /**************************************
19  * A Statement tree walker that will visit each Statement s in the tree,
20  * in depth-first evaluation order, and call fp(s,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 
29 class PostorderStatementVisitor : public StoppableVisitor
30 {
31 public:
32     StoppableVisitor *v;
33     PostorderStatementVisitor(StoppableVisitor *v) : v(v) {}
34 
35     bool doCond(Statement *s)
36     {
37         if (!stop && s)
38             s->accept(this);
39         return stop;
40     }
41     bool applyTo(Statement *s)
42     {
43         s->accept(v);
44         stop = v->stop;
45         return true;
46     }
47 
48     void visit(Statement *s)
49     {
50         applyTo(s);
51     }
52     void visit(PeelStatement *s)
53     {
54         doCond(s->s) || applyTo(s);
55     }
56     void visit(CompoundStatement *s)
57     {
58         for (size_t i = 0; i < s->statements->dim; i++)
59             if (doCond((*s->statements)[i]))
60                 return;
61         applyTo(s);
62     }
63     void visit(UnrolledLoopStatement *s)
64     {
65         for (size_t i = 0; i < s->statements->dim; i++)
66             if (doCond((*s->statements)[i]))
67                 return;
68         applyTo(s);
69     }
70     void visit(ScopeStatement *s)
71     {
72         doCond(s->statement) || applyTo(s);
73     }
74     void visit(WhileStatement *s)
75     {
76         doCond(s->_body) || applyTo(s);
77     }
78     void visit(DoStatement *s)
79     {
80         doCond(s->_body) || applyTo(s);
81     }
82     void visit(ForStatement *s)
83     {
84         doCond(s->_init) || doCond(s->_body) || applyTo(s);
85     }
86     void visit(ForeachStatement *s)
87     {
88         doCond(s->_body) || applyTo(s);
89     }
90     void visit(ForeachRangeStatement *s)
91     {
92         doCond(s->_body) || applyTo(s);
93     }
94     void visit(IfStatement *s)
95     {
96         doCond(s->ifbody) || doCond(s->elsebody) || applyTo(s);
97     }
98     void visit(PragmaStatement *s)
99     {
100         doCond(s->_body) || applyTo(s);
101     }
102     void visit(SwitchStatement *s)
103     {
104         doCond(s->_body) || applyTo(s);
105     }
106     void visit(CaseStatement *s)
107     {
108         doCond(s->statement) || applyTo(s);
109     }
110     void visit(DefaultStatement *s)
111     {
112         doCond(s->statement) || applyTo(s);
113     }
114     void visit(SynchronizedStatement *s)
115     {
116         doCond(s->_body) || applyTo(s);
117     }
118     void visit(WithStatement *s)
119     {
120         doCond(s->_body) || applyTo(s);
121     }
122     void visit(TryCatchStatement *s)
123     {
124         if (doCond(s->_body))
125             return;
126 
127         for (size_t i = 0; i < s->catches->dim; i++)
128             if (doCond((*s->catches)[i]->handler))
129                 return;
130         applyTo(s);
131     }
132     void visit(TryFinallyStatement *s)
133     {
134         doCond(s->_body) || doCond(s->finalbody) || applyTo(s);
135     }
136     void visit(OnScopeStatement *s)
137     {
138         doCond(s->statement) || applyTo(s);
139     }
140     void visit(DebugStatement *s)
141     {
142         doCond(s->statement) || applyTo(s);
143     }
144     void visit(LabelStatement *s)
145     {
146         doCond(s->statement) || applyTo(s);
147     }
148 };
149 
150 bool walkPostorder(Statement *s, StoppableVisitor *v)
151 {
152     PostorderStatementVisitor pv(v);
153     s->accept(&pv);
154     return v->stop;
155 }
156