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/intermediate.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	{
48		visit = it->visitBinary(PreVisit, this);
49	}
50
51	//
52	// Visit the children, in the right order.
53	//
54	if(visit)
55	{
56		it->incrementDepth();
57
58		if(it->rightToLeft)
59		{
60			if(right)
61			{
62				right->traverse(it);
63			}
64
65			if(it->inVisit)
66			{
67				visit = it->visitBinary(InVisit, this);
68			}
69
70			if(visit && left)
71			{
72				left->traverse(it);
73			}
74		}
75		else
76		{
77			if(left)
78			{
79				left->traverse(it);
80			}
81
82			if(it->inVisit)
83			{
84				visit = it->visitBinary(InVisit, this);
85			}
86
87			if(visit && right)
88			{
89				right->traverse(it);
90			}
91		}
92
93		it->decrementDepth();
94	}
95
96	//
97	// Visit the node after the children, if requested and the traversal
98	// hasn't been cancelled yet.
99	//
100	if(visit && it->postVisit)
101	{
102		it->visitBinary(PostVisit, this);
103	}
104}
105
106//
107// Traverse a unary node.  Same comments in binary node apply here.
108//
109void TIntermUnary::traverse(TIntermTraverser* it)
110{
111	bool visit = true;
112
113	if (it->preVisit)
114		visit = it->visitUnary(PreVisit, this);
115
116	if (visit) {
117		it->incrementDepth();
118		operand->traverse(it);
119		it->decrementDepth();
120	}
121
122	if (visit && it->postVisit)
123		it->visitUnary(PostVisit, this);
124}
125
126//
127// Traverse an aggregate node.  Same comments in binary node apply here.
128//
129void TIntermAggregate::traverse(TIntermTraverser* it)
130{
131	bool visit = true;
132
133	if(it->preVisit)
134	{
135		visit = it->visitAggregate(PreVisit, this);
136	}
137
138	if(visit)
139	{
140		it->incrementDepth();
141
142		if(it->rightToLeft)
143		{
144			for(TIntermSequence::reverse_iterator sit = sequence.rbegin(); sit != sequence.rend(); sit++)
145			{
146				(*sit)->traverse(it);
147
148				if(visit && it->inVisit)
149				{
150					if(*sit != sequence.front())
151					{
152						visit = it->visitAggregate(InVisit, this);
153					}
154				}
155			}
156		}
157		else
158		{
159			for(TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++)
160			{
161				(*sit)->traverse(it);
162
163				if(visit && it->inVisit)
164				{
165					if(*sit != sequence.back())
166					{
167						visit = it->visitAggregate(InVisit, this);
168					}
169				}
170			}
171		}
172
173		it->decrementDepth();
174	}
175
176	if(visit && it->postVisit)
177	{
178		it->visitAggregate(PostVisit, this);
179	}
180}
181
182//
183// Traverse a selection node.  Same comments in binary node apply here.
184//
185void TIntermSelection::traverse(TIntermTraverser* it)
186{
187	bool visit = true;
188
189	if (it->preVisit)
190		visit = it->visitSelection(PreVisit, this);
191
192	if (visit) {
193		it->incrementDepth();
194		if (it->rightToLeft) {
195			if (falseBlock)
196				falseBlock->traverse(it);
197			if (trueBlock)
198				trueBlock->traverse(it);
199			condition->traverse(it);
200		} else {
201			condition->traverse(it);
202			if (trueBlock)
203				trueBlock->traverse(it);
204			if (falseBlock)
205				falseBlock->traverse(it);
206		}
207		it->decrementDepth();
208	}
209
210	if (visit && it->postVisit)
211		it->visitSelection(PostVisit, this);
212}
213
214//
215// Traverse a loop node.  Same comments in binary node apply here.
216//
217void TIntermLoop::traverse(TIntermTraverser* it)
218{
219	bool visit = true;
220
221	if(it->preVisit)
222	{
223		visit = it->visitLoop(PreVisit, this);
224	}
225
226	if(visit)
227	{
228		it->incrementDepth();
229
230		if(it->rightToLeft)
231		{
232			if(expr)
233			{
234				expr->traverse(it);
235			}
236
237			if(body)
238			{
239				body->traverse(it);
240			}
241
242			if(cond)
243			{
244				cond->traverse(it);
245			}
246		}
247		else
248		{
249			if(cond)
250			{
251				cond->traverse(it);
252			}
253
254			if(body)
255			{
256				body->traverse(it);
257			}
258
259			if(expr)
260			{
261				expr->traverse(it);
262			}
263		}
264
265		it->decrementDepth();
266	}
267
268	if(visit && it->postVisit)
269	{
270		it->visitLoop(PostVisit, this);
271	}
272}
273
274//
275// Traverse a branch node.  Same comments in binary node apply here.
276//
277void TIntermBranch::traverse(TIntermTraverser* it)
278{
279	bool visit = true;
280
281	if (it->preVisit)
282		visit = it->visitBranch(PreVisit, this);
283
284	if (visit && expression) {
285		it->incrementDepth();
286		expression->traverse(it);
287		it->decrementDepth();
288	}
289
290	if (visit && it->postVisit)
291		it->visitBranch(PostVisit, this);
292}
293
294