1//
2// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7#include "compiler/translator/IntermNode.h"
8
9//
10// Traverse the intermediate representation tree, and
11// call a node type specific function for each node.
12// Done recursively through the member function Traverse().
13// Node types can be skipped if their function to call is 0,
14// but their subtree will still be traversed.
15// Nodes with children can have their whole subtree skipped
16// if preVisit is turned on and the type specific function
17// returns false.
18//
19// preVisit, postVisit, and rightToLeft control what order
20// nodes are visited in.
21//
22
23//
24// Traversal functions for terminals are straighforward....
25//
26void TIntermSymbol::traverse(TIntermTraverser *it)
27{
28    it->visitSymbol(this);
29}
30
31void TIntermConstantUnion::traverse(TIntermTraverser *it)
32{
33    it->visitConstantUnion(this);
34}
35
36//
37// Traverse a binary node.
38//
39void TIntermBinary::traverse(TIntermTraverser *it)
40{
41    bool visit = true;
42
43    //
44    // visit the node before children if pre-visiting.
45    //
46    if (it->preVisit)
47        visit = it->visitBinary(PreVisit, this);
48
49    //
50    // Visit the children, in the right order.
51    //
52    if (visit)
53    {
54        it->incrementDepth(this);
55
56        if (it->rightToLeft)
57        {
58            if (mRight)
59                mRight->traverse(it);
60
61            if (it->inVisit)
62                visit = it->visitBinary(InVisit, this);
63
64            if (visit && mLeft)
65                mLeft->traverse(it);
66        }
67        else
68        {
69            if (mLeft)
70                mLeft->traverse(it);
71
72            if (it->inVisit)
73                visit = it->visitBinary(InVisit, this);
74
75            if (visit && mRight)
76                mRight->traverse(it);
77        }
78
79        it->decrementDepth();
80    }
81
82    //
83    // Visit the node after the children, if requested and the traversal
84    // hasn't been cancelled yet.
85    //
86    if (visit && it->postVisit)
87        it->visitBinary(PostVisit, this);
88}
89
90//
91// Traverse a unary node.  Same comments in binary node apply here.
92//
93void TIntermUnary::traverse(TIntermTraverser *it)
94{
95    bool visit = true;
96
97    if (it->preVisit)
98        visit = it->visitUnary(PreVisit, this);
99
100    if (visit) {
101        it->incrementDepth(this);
102        mOperand->traverse(it);
103        it->decrementDepth();
104    }
105
106    if (visit && it->postVisit)
107        it->visitUnary(PostVisit, this);
108}
109
110//
111// Traverse an aggregate node.  Same comments in binary node apply here.
112//
113void TIntermAggregate::traverse(TIntermTraverser *it)
114{
115    bool visit = true;
116
117    if (it->preVisit)
118        visit = it->visitAggregate(PreVisit, this);
119
120    if (visit)
121    {
122        it->incrementDepth(this);
123
124        if (it->rightToLeft)
125        {
126            for (TIntermSequence::reverse_iterator sit = mSequence.rbegin();
127                 sit != mSequence.rend(); sit++)
128            {
129                (*sit)->traverse(it);
130
131                if (visit && it->inVisit)
132                {
133                    if (*sit != mSequence.front())
134                        visit = it->visitAggregate(InVisit, this);
135                }
136            }
137        }
138        else
139        {
140            for (TIntermSequence::iterator sit = mSequence.begin();
141                 sit != mSequence.end(); sit++)
142            {
143                (*sit)->traverse(it);
144
145                if (visit && it->inVisit)
146                {
147                    if (*sit != mSequence.back())
148                        visit = it->visitAggregate(InVisit, this);
149                }
150            }
151        }
152
153        it->decrementDepth();
154    }
155
156    if (visit && it->postVisit)
157        it->visitAggregate(PostVisit, this);
158}
159
160//
161// Traverse a selection node.  Same comments in binary node apply here.
162//
163void TIntermSelection::traverse(TIntermTraverser *it)
164{
165    bool visit = true;
166
167    if (it->preVisit)
168        visit = it->visitSelection(PreVisit, this);
169
170    if (visit)
171    {
172        it->incrementDepth(this);
173        if (it->rightToLeft)
174        {
175            if (mFalseBlock)
176                mFalseBlock->traverse(it);
177            if (mTrueBlock)
178                mTrueBlock->traverse(it);
179            mCondition->traverse(it);
180        }
181        else
182        {
183            mCondition->traverse(it);
184            if (mTrueBlock)
185                mTrueBlock->traverse(it);
186            if (mFalseBlock)
187                mFalseBlock->traverse(it);
188        }
189        it->decrementDepth();
190    }
191
192    if (visit && it->postVisit)
193        it->visitSelection(PostVisit, this);
194}
195
196//
197// Traverse a loop node.  Same comments in binary node apply here.
198//
199void TIntermLoop::traverse(TIntermTraverser *it)
200{
201    bool visit = true;
202
203    if (it->preVisit)
204        visit = it->visitLoop(PreVisit, this);
205
206    if (visit)
207    {
208        it->incrementDepth(this);
209
210        if (it->rightToLeft)
211        {
212            if (mExpr)
213                mExpr->traverse(it);
214
215            if (mBody)
216                mBody->traverse(it);
217
218            if (mCond)
219                mCond->traverse(it);
220
221            if (mInit)
222                mInit->traverse(it);
223        }
224        else
225        {
226            if (mInit)
227                mInit->traverse(it);
228
229            if (mCond)
230                mCond->traverse(it);
231
232            if (mBody)
233                mBody->traverse(it);
234
235            if (mExpr)
236                mExpr->traverse(it);
237        }
238
239        it->decrementDepth();
240    }
241
242    if (visit && it->postVisit)
243        it->visitLoop(PostVisit, this);
244}
245
246//
247// Traverse a branch node.  Same comments in binary node apply here.
248//
249void TIntermBranch::traverse(TIntermTraverser *it)
250{
251    bool visit = true;
252
253    if (it->preVisit)
254        visit = it->visitBranch(PreVisit, this);
255
256    if (visit && mExpression) {
257        it->incrementDepth(this);
258        mExpression->traverse(it);
259        it->decrementDepth();
260    }
261
262    if (visit && it->postVisit)
263        it->visitBranch(PostVisit, this);
264}
265
266void TIntermRaw::traverse(TIntermTraverser *it)
267{
268    it->visitRaw(this);
269}
270