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