glslang: Fix over 100 warnings from MSVC warning level 4.
[platform/upstream/glslang.git] / glslang / Include / intermediate.h
1 //
2 //Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
3 //Copyright (C) 2012-2013 LunarG, Inc.
4 //
5 //All rights reserved.
6 //
7 //Redistribution and use in source and binary forms, with or without
8 //modification, are permitted provided that the following conditions
9 //are met:
10 //
11 //    Redistributions of source code must retain the above copyright
12 //    notice, this list of conditions and the following disclaimer.
13 //
14 //    Redistributions in binary form must reproduce the above
15 //    copyright notice, this list of conditions and the following
16 //    disclaimer in the documentation and/or other materials provided
17 //    with the distribution.
18 //
19 //    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
20 //    contributors may be used to endorse or promote products derived
21 //    from this software without specific prior written permission.
22 //
23 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 //"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 //LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 //FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27 //COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28 //INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 //BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 //LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31 //CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 //LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33 //ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 //POSSIBILITY OF SUCH DAMAGE.
35 //
36
37 //
38 // Definition of the in-memory high-level intermediate representation
39 // of shaders.  This is a tree that parser creates.
40 //
41 // Nodes in the tree are defined as a hierarchy of classes derived from 
42 // TIntermNode. Each is a node in a tree.  There is no preset branching factor;
43 // each node can have it's own type of list of children.
44 //
45
46 #ifndef __INTERMEDIATE_H
47 #define __INTERMEDIATE_H
48
49 #include "../Include/Common.h"
50 #include "../Include/Types.h"
51 #include "../Include/ConstantUnion.h"
52
53 namespace glslang {
54
55 //
56 // Operators used by the high-level (parse tree) representation.
57 //
58 enum TOperator {
59     EOpNull,            // if in a node, should only mean a node is still being built
60     EOpSequence,        // denotes a list of statements, or parameters, etc.
61     EOpLinkerObjects,   // for aggregate node of objects the linker may need, if not reference by the rest of the AST
62     EOpFunctionCall,    
63     EOpFunction,        // For function definition
64     EOpParameters,      // an aggregate listing the parameters to a function
65
66     //
67     // Unary operators
68     //
69     
70     EOpNegative,
71     EOpLogicalNot,
72     EOpVectorLogicalNot,
73     EOpBitwiseNot,
74
75     EOpPostIncrement,
76     EOpPostDecrement,
77     EOpPreIncrement,
78     EOpPreDecrement,
79
80     EOpConvIntToBool,
81     EOpConvUintToBool,
82     EOpConvFloatToBool,
83     EOpConvDoubleToBool,
84     EOpConvBoolToFloat,
85     EOpConvIntToFloat,
86     EOpConvUintToFloat,
87     EOpConvDoubleToFloat,
88     EOpConvUintToInt,
89     EOpConvFloatToInt,
90     EOpConvBoolToInt,
91     EOpConvDoubleToInt,
92     EOpConvIntToUint,
93     EOpConvFloatToUint,
94     EOpConvBoolToUint,
95     EOpConvDoubleToUint,
96     EOpConvIntToDouble,
97     EOpConvUintToDouble,
98     EOpConvFloatToDouble,
99     EOpConvBoolToDouble,
100
101     //
102     // binary operations
103     //
104
105     EOpAdd,
106     EOpSub,
107     EOpMul,
108     EOpDiv,
109     EOpMod,
110     EOpRightShift,
111     EOpLeftShift,
112     EOpAnd,
113     EOpInclusiveOr,
114     EOpExclusiveOr,
115     EOpEqual,
116     EOpNotEqual,
117     EOpVectorEqual,
118     EOpVectorNotEqual,
119     EOpLessThan,
120     EOpGreaterThan,
121     EOpLessThanEqual,
122     EOpGreaterThanEqual,
123     EOpComma,
124
125     EOpVectorTimesScalar,
126     EOpVectorTimesMatrix,
127     EOpMatrixTimesVector,
128     EOpMatrixTimesScalar,
129
130     EOpLogicalOr,
131     EOpLogicalXor,
132     EOpLogicalAnd,
133
134     EOpIndexDirect,
135     EOpIndexIndirect,
136     EOpIndexDirectStruct,
137
138     EOpVectorSwizzle,
139
140     EOpMethod,
141
142     //
143     // Built-in functions potentially mapped to operators
144     //
145
146     EOpRadians,
147     EOpDegrees,
148     EOpSin,
149     EOpCos,
150     EOpTan,
151     EOpAsin,
152     EOpAcos,
153     EOpAtan,
154     EOpSinh,
155     EOpCosh,
156     EOpTanh,
157     EOpAsinh,
158     EOpAcosh,
159     EOpAtanh,
160
161     EOpPow,
162     EOpExp,
163     EOpLog,
164     EOpExp2,
165     EOpLog2,
166     EOpSqrt,
167     EOpInverseSqrt,
168
169     EOpAbs,
170     EOpSign,
171     EOpFloor,
172     EOpTrunc,
173     EOpRound,
174     EOpRoundEven,
175     EOpCeil,
176     EOpFract,
177     EOpModf,
178     EOpMin,
179     EOpMax,
180     EOpClamp,
181     EOpMix,
182     EOpStep,
183     EOpSmoothStep,
184
185     EOpIsNan,
186     EOpIsInf,
187
188     EOpFloatBitsToInt,
189     EOpFloatBitsToUint,
190     EOpIntBitsToFloat,
191     EOpUintBitsToFloat,
192     EOpPackSnorm2x16,
193     EOpUnpackSnorm2x16,
194     EOpPackUnorm2x16,
195     EOpUnpackUnorm2x16,
196     EOpPackHalf2x16,
197     EOpUnpackHalf2x16,
198
199     EOpLength,
200     EOpDistance,
201     EOpDot,
202     EOpCross,
203     EOpNormalize,
204     EOpFaceForward,
205     EOpReflect,
206     EOpRefract,
207
208     EOpDPdx,            // Fragment only
209     EOpDPdy,            // Fragment only
210     EOpFwidth,          // Fragment only
211     EOpDPdxFine,        // Fragment only
212     EOpDPdyFine,        // Fragment only
213     EOpFwidthFine,      // Fragment only
214     EOpDPdxCoarse,      // Fragment only
215     EOpDPdyCoarse,      // Fragment only
216     EOpFwidthCoarse,    // Fragment only
217
218     EOpMatrixTimesMatrix,
219     EOpOuterProduct,
220     EOpDeterminant,
221     EOpMatrixInverse,
222     EOpTranspose,
223
224     EOpEmitVertex,           // geometry only
225     EOpEndPrimitive,         // geometry only
226     EOpEmitStreamVertex,     // geometry only
227     EOpEndStreamPrimitive,   // geometry only
228
229     EOpBarrier,
230     EOpMemoryBarrier,
231     EOpMemoryBarrierAtomicCounter,
232     EOpMemoryBarrierBuffer,
233     EOpMemoryBarrierImage,
234     EOpMemoryBarrierShared,  // compute only
235     EOpGroupMemoryBarrier,   // compute only
236
237     EOpAtomicAdd,            // TODO: AST functionality: hook these up
238     EOpAtomicMin,
239     EOpAtomicMax,
240     EOpAtomicAnd,
241     EOpAtomicOr,
242     EOpAtomicXor,
243     EOpAtomicExchange,
244     EOpAtomicCompSwap,
245
246     EOpAny,
247     EOpAll,
248
249     //
250     // Branch
251     //
252
253     EOpKill,            // Fragment only
254     EOpReturn,
255     EOpBreak,
256     EOpContinue,
257     EOpCase,
258     EOpDefault,
259
260     //
261     // Constructors
262     //
263
264     EOpConstructGuardStart,
265     EOpConstructInt,          // these first scalar forms also identify what implicit conversion is needed
266     EOpConstructUint,
267     EOpConstructBool,
268     EOpConstructFloat,
269     EOpConstructDouble,
270     EOpConstructVec2,
271     EOpConstructVec3,
272     EOpConstructVec4,
273     EOpConstructDVec2,
274     EOpConstructDVec3,
275     EOpConstructDVec4,
276     EOpConstructBVec2,
277     EOpConstructBVec3,
278     EOpConstructBVec4,
279     EOpConstructIVec2,
280     EOpConstructIVec3,
281     EOpConstructIVec4,
282     EOpConstructUVec2,
283     EOpConstructUVec3,
284     EOpConstructUVec4,
285     EOpConstructMat2x2,
286     EOpConstructMat2x3,
287     EOpConstructMat2x4,
288     EOpConstructMat3x2,
289     EOpConstructMat3x3,
290     EOpConstructMat3x4,
291     EOpConstructMat4x2,
292     EOpConstructMat4x3,
293     EOpConstructMat4x4,
294     EOpConstructDMat2x2,
295     EOpConstructDMat2x3,
296     EOpConstructDMat2x4,
297     EOpConstructDMat3x2,
298     EOpConstructDMat3x3,
299     EOpConstructDMat3x4,
300     EOpConstructDMat4x2,
301     EOpConstructDMat4x3,
302     EOpConstructDMat4x4,
303     EOpConstructStruct,
304     EOpConstructGuardEnd,
305
306     //
307     // moves
308     //
309     
310     EOpAssign,
311     EOpAddAssign,
312     EOpSubAssign,
313     EOpMulAssign,
314     EOpVectorTimesMatrixAssign,
315     EOpVectorTimesScalarAssign,
316     EOpMatrixTimesScalarAssign,
317     EOpMatrixTimesMatrixAssign,
318     EOpDivAssign,
319     EOpModAssign,
320     EOpAndAssign,
321     EOpInclusiveOrAssign,
322     EOpExclusiveOrAssign,
323     EOpLeftShiftAssign,
324     EOpRightShiftAssign,
325
326     //
327     // Array operators
328     //
329
330     EOpArrayLength,      // "Array" distinguishes from length(v) built-in function, but it applies to vectors and matrices as well.
331 };
332
333 class TIntermTraverser;
334 class TIntermOperator;
335 class TIntermAggregate;
336 class TIntermUnary;
337 class TIntermBinary;
338 class TIntermConstantUnion;
339 class TIntermSelection;
340 class TIntermSwitch;
341 class TIntermBranch;
342 class TIntermTyped;
343 class TIntermMethod;
344 class TIntermSymbol;
345
346 } // end namespace glslang
347
348 //
349 // Base class for the tree nodes
350 //
351 // (Put outside the glslang namespace, as it's used as part of the external interface.)
352 //
353 class TIntermNode {
354 public:
355     POOL_ALLOCATOR_NEW_DELETE(glslang::GetThreadPoolAllocator())
356
357     TIntermNode() { loc.line = 0; loc.string = 0; }
358     virtual glslang::TSourceLoc getLoc() const { return loc; }
359     virtual void setLoc(glslang::TSourceLoc l) { loc = l; }
360     virtual void traverse(glslang::TIntermTraverser*) = 0;
361     virtual       glslang::TIntermTyped*         getAsTyped()               { return 0; }
362     virtual       glslang::TIntermOperator*      getAsOperator()            { return 0; }
363     virtual       glslang::TIntermConstantUnion* getAsConstantUnion()       { return 0; }
364     virtual       glslang::TIntermAggregate*     getAsAggregate()           { return 0; }
365     virtual       glslang::TIntermUnary*         getAsUnaryNode()           { return 0; }
366     virtual       glslang::TIntermBinary*        getAsBinaryNode()          { return 0; }
367     virtual       glslang::TIntermSelection*     getAsSelectionNode()       { return 0; }
368     virtual       glslang::TIntermSwitch*        getAsSwitchNode()          { return 0; }
369     virtual       glslang::TIntermMethod*        getAsMethodNode()          { return 0; }
370     virtual       glslang::TIntermSymbol*        getAsSymbolNode()          { return 0; }
371     virtual       glslang::TIntermBranch*        getAsBranchNode()          { return 0; }
372
373     virtual const glslang::TIntermTyped*         getAsTyped()         const { return 0; }
374     virtual const glslang::TIntermOperator*      getAsOperator()      const { return 0; }
375     virtual const glslang::TIntermConstantUnion* getAsConstantUnion() const { return 0; }
376     virtual const glslang::TIntermAggregate*     getAsAggregate()     const { return 0; }
377     virtual const glslang::TIntermUnary*         getAsUnaryNode()     const { return 0; }
378     virtual const glslang::TIntermBinary*        getAsBinaryNode()    const { return 0; }
379     virtual const glslang::TIntermSelection*     getAsSelectionNode() const { return 0; }
380     virtual const glslang::TIntermSwitch*        getAsSwitchNode()    const { return 0; }
381     virtual const glslang::TIntermMethod*        getAsMethodNode()    const { return 0; }
382     virtual const glslang::TIntermSymbol*        getAsSymbolNode()    const { return 0; }
383     virtual const glslang::TIntermBranch*        getAsBranchNode()    const { return 0; }
384     virtual ~TIntermNode() { }
385 protected:
386     glslang::TSourceLoc loc;
387 };
388
389 namespace glslang {
390
391 //
392 // This is just to help yacc.
393 //
394 struct TIntermNodePair {
395     TIntermNode* node1;
396     TIntermNode* node2;
397 };
398
399 //
400 // Intermediate class for nodes that have a type.
401 //
402 class TIntermTyped : public TIntermNode {
403 public:
404         TIntermTyped(const TType& t) { type.shallowCopy(t); }
405     virtual       TIntermTyped* getAsTyped()       { return this; }
406     virtual const TIntermTyped* getAsTyped() const { return this; }
407     virtual void setType(const TType& t) { type.shallowCopy(t); }
408     virtual const TType& getType() const { return type; }
409     virtual TType& getWritableType() { return type; }
410     
411     virtual TBasicType getBasicType() const { return type.getBasicType(); }
412     virtual TQualifier& getQualifier() { return type.getQualifier(); }
413     virtual const TQualifier& getQualifier() const { return type.getQualifier(); }
414     virtual void propagatePrecision(TPrecisionQualifier);
415     virtual int getVectorSize() const { return type.getVectorSize(); }
416     virtual int getMatrixCols() const { return type.getMatrixCols(); }
417     virtual int getMatrixRows() const { return type.getMatrixRows(); }
418     virtual bool isMatrix() const { return type.isMatrix(); }
419     virtual bool isArray()  const { return type.isArray(); }
420     virtual bool isVector() const { return type.isVector(); }
421     virtual bool isScalar() const { return type.isScalar(); }
422     virtual bool isStruct() const { return type.isStruct(); }
423     TString getCompleteString() const { return type.getCompleteString(); }
424
425 protected:
426     TType type;
427 };
428
429 //
430 // Handle for, do-while, and while loops.
431 //
432 class TIntermLoop : public TIntermNode {
433 public:
434     TIntermLoop(TIntermNode* aBody, TIntermTyped* aTest, TIntermTyped* aTerminal, bool testFirst) : 
435         body(aBody),
436         test(aTest),
437         terminal(aTerminal),
438         first(testFirst) { }
439     virtual void traverse(TIntermTraverser*);
440     TIntermNode*  getBody() { return body; }
441     TIntermTyped* getTest() { return test; }
442     TIntermTyped* getTerminal() { return terminal; }
443     bool testFirst() { return first; }
444 protected:
445     TIntermNode* body;       // code to loop over
446     TIntermTyped* test;      // exit condition associated with loop, could be 0 for 'for' loops
447     TIntermTyped* terminal;  // exists for for-loops
448     bool first;              // true for while and for, not for do-while
449 };
450
451 //
452 // Handle case, break, continue, return, and kill.
453 //
454 class TIntermBranch : public TIntermNode {
455 public:
456     TIntermBranch(TOperator op, TIntermTyped* e) :
457         flowOp(op),
458         expression(e) { }
459     virtual       TIntermBranch* getAsBranchNode()       { return this; }
460     virtual const TIntermBranch* getAsBranchNode() const { return this; }
461     virtual void traverse(TIntermTraverser*);
462     TOperator getFlowOp() { return flowOp; }
463     TIntermTyped* getExpression() { return expression; }
464 protected:
465     TOperator flowOp;
466     TIntermTyped* expression;
467 };
468
469 //
470 // Represent method names before seeing their calling signature
471 // or resolving them to operations.  Just an expression as the base object
472 // and a textural name.
473 //
474 class TIntermMethod : public TIntermTyped {
475 public:
476     TIntermMethod(TIntermTyped* o, const TType& t, const TString& m) : TIntermTyped(t), object(o), method(m) { }
477     virtual       TIntermMethod* getAsMethodNode()       { return this; }
478     virtual const TIntermMethod* getAsMethodNode() const { return this; }
479     virtual const TString& getMethodName() const { return method; }
480     virtual TIntermTyped* getObject() const { return object; }
481     virtual void traverse(TIntermTraverser*);
482 protected:
483     TIntermTyped* object;
484     TString method;
485 };
486
487 //
488 // Nodes that correspond to symbols or constants in the source code.
489 //
490 class TIntermSymbol : public TIntermTyped {
491 public:
492         // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. If sym comes from
493         // per process threadPoolAllocator, then it causes increased memory usage per compile
494         // it is essential to use "symbol = sym" to assign to symbol
495     TIntermSymbol(int i, const TString& n, const TType& t) : 
496         TIntermTyped(t), id(i) { name = n;} 
497     virtual int getId() const { return id; }
498     virtual const TString& getName() const { return name; }
499     virtual void traverse(TIntermTraverser*);
500     virtual       TIntermSymbol* getAsSymbolNode()       { return this; }
501     virtual const TIntermSymbol* getAsSymbolNode() const { return this; }
502     void setConstArray(const TConstUnionArray& c) { unionArray = c; }
503     const TConstUnionArray& getConstArray() const { return unionArray; }
504 protected:
505     int id;
506     TString name;
507     TConstUnionArray unionArray;
508 };
509
510 class TIntermConstantUnion : public TIntermTyped {
511 public:
512     TIntermConstantUnion(const TConstUnionArray& ua, const TType& t) : TIntermTyped(t), unionArray(ua), literal(false) { }
513     const TConstUnionArray& getConstArray() const { return unionArray; }
514     virtual       TIntermConstantUnion* getAsConstantUnion()       { return this; }
515     virtual const TIntermConstantUnion* getAsConstantUnion() const { return this; }
516     virtual void traverse(TIntermTraverser*);
517     virtual TIntermTyped* fold(TOperator, const TIntermTyped*) const;
518     virtual TIntermTyped* fold(TOperator, const TType&) const;
519     void setLiteral() { literal = true; }
520     void setExpression() { literal = false; }
521     bool isLiteral() const { return literal; }
522 protected:
523     const TConstUnionArray unionArray;
524     bool literal;  // true if node represents a literal in the source code
525 };
526
527 //
528 // Intermediate class for node types that hold operators.
529 //
530 class TIntermOperator : public TIntermTyped {
531 public:
532     virtual       TIntermOperator* getAsOperator()       { return this; }
533     virtual const TIntermOperator* getAsOperator() const { return this; }
534     TOperator getOp() { return op; }
535     bool modifiesState() const;
536     bool isConstructor() const;
537     virtual bool promote() { return true; }
538 protected:
539     TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat)), op(o) {}
540     TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o) {}   
541     TOperator op;
542 };
543
544 //
545 // Nodes for all the basic binary math operators.
546 //
547 class TIntermBinary : public TIntermOperator {
548 public:
549     TIntermBinary(TOperator o) : TIntermOperator(o) {}
550     virtual void traverse(TIntermTraverser*);
551     virtual void setLeft(TIntermTyped* n) { left = n; }
552     virtual void setRight(TIntermTyped* n) { right = n; }
553     virtual TIntermTyped* getLeft() const { return left; }
554     virtual TIntermTyped* getRight() const { return right; }
555     virtual       TIntermBinary* getAsBinaryNode()       { return this; }
556     virtual const TIntermBinary* getAsBinaryNode() const { return this; }
557     virtual bool promote();
558     virtual void updatePrecision();
559 protected:
560     TIntermTyped* left;
561     TIntermTyped* right;
562 };
563
564 //
565 // Nodes for unary math operators.
566 //
567 class TIntermUnary : public TIntermOperator {
568 public:
569     TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0) {}
570     TIntermUnary(TOperator o) : TIntermOperator(o), operand(0) {}
571     virtual void traverse(TIntermTraverser*);
572     virtual void setOperand(TIntermTyped* o) { operand = o; }
573     virtual TIntermTyped* getOperand() { return operand; }
574     virtual       TIntermUnary* getAsUnaryNode()       { return this; }
575     virtual const TIntermUnary* getAsUnaryNode() const { return this; }
576     virtual bool promote();
577     virtual void updatePrecision();
578 protected:
579     TIntermTyped* operand;
580 };
581
582 typedef TVector<TIntermNode*> TIntermSequence;
583 typedef TVector<int> TQualifierList;
584 //
585 // Nodes that operate on an arbitrary sized set of children.
586 //
587 class TIntermAggregate : public TIntermOperator {
588 public:
589     TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), pragmaTable(0) { }
590     TIntermAggregate(TOperator o) : TIntermOperator(o), pragmaTable(0) { }
591         ~TIntermAggregate() { delete pragmaTable; }
592     virtual       TIntermAggregate* getAsAggregate()       { return this; }
593     virtual const TIntermAggregate* getAsAggregate() const { return this; }
594     virtual void setOperator(TOperator o) { op = o; }
595     virtual TIntermSequence& getSequence() { return sequence; }
596     virtual const TIntermSequence& getSequence() const { return sequence; }
597         virtual void setName(const TString& n) { name = n; }
598     virtual const TString& getName() const { return name; }
599     virtual void traverse(TIntermTraverser*);
600     virtual void setUserDefined() { userDefined = true; }
601     virtual bool isUserDefined() { return userDefined; }
602     virtual TQualifierList& getQualifierList() { return qualifier; }
603     virtual const TQualifierList& getQualifierList() const { return qualifier; }
604         void setOptimize(bool o) { optimize = o; }
605         void setDebug(bool d) { debug = d; }
606         bool getOptimize() { return optimize; }
607         bool getDebug() { return debug; }
608         void addToPragmaTable(const TPragmaTable& pTable);
609         const TPragmaTable& getPragmaTable() const { return *pragmaTable; }
610 protected:
611         TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
612         TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator
613     TIntermSequence sequence;
614     TQualifierList qualifier;
615         TString name;
616     bool userDefined; // used for user defined function names
617         bool optimize;
618         bool debug;
619         TPragmaTable* pragmaTable;
620 };
621
622 //
623 // For if tests.
624 //
625 class TIntermSelection : public TIntermTyped {
626 public:
627     TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) :
628         TIntermTyped(TType(EbtVoid)), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
629     TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) :
630         TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
631     virtual void traverse(TIntermTraverser*);
632     virtual TIntermTyped* getCondition() const { return condition; }
633     virtual TIntermNode* getTrueBlock() const { return trueBlock; }
634     virtual TIntermNode* getFalseBlock() const { return falseBlock; }
635     virtual       TIntermSelection* getAsSelectionNode()       { return this; }
636     virtual const TIntermSelection* getAsSelectionNode() const { return this; }
637 protected:
638     TIntermTyped* condition;
639     TIntermNode* trueBlock;
640     TIntermNode* falseBlock;
641 };
642
643 //
644 // For switch statements.  Designed use is that a switch will have sequence of nodes
645 // that are either case/default nodes or a *single* node that represents all the code
646 // in between (if any) consecutive case/defaults.  So, a traversal need only deal with
647 // 0 or 1 nodes per case/default statement.
648 //
649 class TIntermSwitch : public TIntermNode {
650 public:
651     TIntermSwitch(TIntermTyped* cond, TIntermAggregate* b) : condition(cond), body(b) { }
652     virtual void traverse(TIntermTraverser*);
653     virtual TIntermNode* getCondition() const { return condition; }
654     virtual TIntermAggregate* getBody() const { return body; }
655     virtual       TIntermSwitch* getAsSwitchNode()       { return this; }
656     virtual const TIntermSwitch* getAsSwitchNode() const { return this; }
657 protected:
658     TIntermTyped* condition;
659     TIntermAggregate* body;
660 };
661
662 enum TVisit
663 {
664     EvPreVisit,
665     EvInVisit,
666     EvPostVisit
667 };
668
669 //
670 // For traversing the tree.  User should derive from this, 
671 // put their traversal specific data in it, and then pass
672 // it to a Traverse method.
673 //
674 // When using this, just fill in the methods for nodes you want visited.
675 // Return false from a pre-visit to skip visiting that node's subtree.
676 //
677 // Explicitly set postVisit to true if you want post visiting, otherwise,
678 // filled in methods will only be called at pre-visit time (before processing
679 // the subtree).  Similary for inVisit for in-order visiting of nodes with
680 // multiple children.
681 //
682 // If you only want post-visits, explicitly turn off preVisit (and inVisit) 
683 // and turn on postVisit.
684 //
685 class TIntermTraverser {
686 public:
687     POOL_ALLOCATOR_NEW_DELETE(glslang::GetThreadPoolAllocator())
688     TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) :
689             preVisit(preVisit),
690             inVisit(inVisit),
691             postVisit(postVisit),
692             rightToLeft(rightToLeft),
693             depth(0),
694             maxDepth(0) { }
695     virtual ~TIntermTraverser() { }
696
697     virtual void visitSymbol(TIntermSymbol*)               { }
698     virtual void visitConstantUnion(TIntermConstantUnion*) { }
699     virtual bool visitBinary(TVisit, TIntermBinary*)       { return true; }
700     virtual bool visitUnary(TVisit, TIntermUnary*)         { return true; }
701     virtual bool visitSelection(TVisit, TIntermSelection*) { return true; }
702     virtual bool visitAggregate(TVisit, TIntermAggregate*) { return true; }
703     virtual bool visitLoop(TVisit, TIntermLoop*)           { return true; }
704     virtual bool visitBranch(TVisit, TIntermBranch*)       { return true; }
705     virtual bool visitSwitch(TVisit, TIntermSwitch*)       { return true; }
706
707     int getMaxDepth() const { return maxDepth; }
708
709     void incrementDepth(TIntermNode *current)
710     {
711         depth++;
712         maxDepth = std::max(maxDepth, depth);
713         path.push_back(current);
714     }
715
716     void decrementDepth()
717     {
718         depth--;
719         path.pop_back();
720     }
721
722     TIntermNode *getParentNode()
723     {
724         return path.size() == 0 ? NULL : path.back();
725     }
726
727     const bool preVisit;
728     const bool inVisit;
729     const bool postVisit;
730     const bool rightToLeft;
731
732 protected:
733     TIntermTraverser& operator=(TIntermTraverser&);
734
735     int depth;
736     int maxDepth;
737
738     // All the nodes from root to the current node's parent during traversing.
739     TVector<TIntermNode *> path;
740 };
741
742 } // end namespace glslang
743
744 #endif // __INTERMEDIATE_H