303 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			303 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
//
 | 
						|
//Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 | 
						|
//Copyright (C) 2013 LunarG, Inc.
 | 
						|
//Copyright (c) 2002-2010 The ANGLE Project Authors.
 | 
						|
//
 | 
						|
//All rights reserved.
 | 
						|
//
 | 
						|
//Redistribution and use in source and binary forms, with or without
 | 
						|
//modification, are permitted provided that the following conditions
 | 
						|
//are met:
 | 
						|
//
 | 
						|
//    Redistributions of source code must retain the above copyright
 | 
						|
//    notice, this list of conditions and the following disclaimer.
 | 
						|
//
 | 
						|
//    Redistributions in binary form must reproduce the above
 | 
						|
//    copyright notice, this list of conditions and the following
 | 
						|
//    disclaimer in the documentation and/or other materials provided
 | 
						|
//    with the distribution.
 | 
						|
//
 | 
						|
//    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
 | 
						|
//    contributors may be used to endorse or promote products derived
 | 
						|
//    from this software without specific prior written permission.
 | 
						|
//
 | 
						|
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
						|
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
						|
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 | 
						|
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 | 
						|
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
						|
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 | 
						|
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | 
						|
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 | 
						|
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 | 
						|
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 | 
						|
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 | 
						|
//POSSIBILITY OF SUCH DAMAGE.
 | 
						|
//
 | 
						|
 | 
						|
#include "../Include/intermediate.h"
 | 
						|
 | 
						|
namespace glslang {
 | 
						|
 | 
						|
//
 | 
						|
// Traverse the intermediate representation tree, and
 | 
						|
// call a node type specific function for each node.
 | 
						|
// Done recursively through the member function Traverse().
 | 
						|
// Node types can be skipped if their function to call is 0,
 | 
						|
// but their subtree will still be traversed.
 | 
						|
// Nodes with children can have their whole subtree skipped
 | 
						|
// if preVisit is turned on and the type specific function
 | 
						|
// returns false.
 | 
						|
//
 | 
						|
// preVisit, postVisit, and rightToLeft control what order
 | 
						|
// nodes are visited in.
 | 
						|
//
 | 
						|
 | 
						|
//
 | 
						|
// Traversal functions for terminals are straightforward....
 | 
						|
//
 | 
						|
void TIntermMethod::traverse(TIntermTraverser*)
 | 
						|
{
 | 
						|
    // Tree should always resolve all methods as a non-method.
 | 
						|
}
 | 
						|
 | 
						|
void TIntermSymbol::traverse(TIntermTraverser *it)
 | 
						|
{
 | 
						|
    it->visitSymbol(this);
 | 
						|
}
 | 
						|
 | 
						|
void TIntermConstantUnion::traverse(TIntermTraverser *it)
 | 
						|
{
 | 
						|
    it->visitConstantUnion(this);
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// Traverse a binary node.
 | 
						|
//
 | 
						|
void TIntermBinary::traverse(TIntermTraverser *it)
 | 
						|
{
 | 
						|
    bool visit = true;
 | 
						|
 | 
						|
    //
 | 
						|
    // visit the node before children if pre-visiting.
 | 
						|
    //
 | 
						|
    if (it->preVisit)
 | 
						|
        visit = it->visitBinary(EvPreVisit, this);
 | 
						|
 | 
						|
    //
 | 
						|
    // Visit the children, in the right order.
 | 
						|
    //
 | 
						|
    if (visit) {
 | 
						|
        it->incrementDepth(this);
 | 
						|
 | 
						|
        if (it->rightToLeft) {
 | 
						|
            if (right)
 | 
						|
                right->traverse(it);
 | 
						|
 | 
						|
            if (it->inVisit)
 | 
						|
                visit = it->visitBinary(EvInVisit, this);
 | 
						|
 | 
						|
            if (visit && left)
 | 
						|
                left->traverse(it);
 | 
						|
        } else {
 | 
						|
            if (left)
 | 
						|
                left->traverse(it);
 | 
						|
 | 
						|
            if (it->inVisit)
 | 
						|
                visit = it->visitBinary(EvInVisit, this);
 | 
						|
 | 
						|
            if (visit && right)
 | 
						|
                right->traverse(it);
 | 
						|
        }
 | 
						|
 | 
						|
        it->decrementDepth();
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Visit the node after the children, if requested and the traversal
 | 
						|
    // hasn't been canceled yet.
 | 
						|
    //
 | 
						|
    if (visit && it->postVisit)
 | 
						|
        it->visitBinary(EvPostVisit, this);
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// Traverse a unary node.  Same comments in binary node apply here.
 | 
						|
//
 | 
						|
void TIntermUnary::traverse(TIntermTraverser *it)
 | 
						|
{
 | 
						|
    bool visit = true;
 | 
						|
 | 
						|
    if (it->preVisit)
 | 
						|
        visit = it->visitUnary(EvPreVisit, this);
 | 
						|
 | 
						|
    if (visit) {
 | 
						|
        it->incrementDepth(this);
 | 
						|
        operand->traverse(it);
 | 
						|
        it->decrementDepth();
 | 
						|
    }
 | 
						|
 | 
						|
    if (visit && it->postVisit)
 | 
						|
        it->visitUnary(EvPostVisit, this);
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// Traverse an aggregate node.  Same comments in binary node apply here.
 | 
						|
//
 | 
						|
void TIntermAggregate::traverse(TIntermTraverser *it)
 | 
						|
{
 | 
						|
    bool visit = true;
 | 
						|
 | 
						|
    if (it->preVisit)
 | 
						|
        visit = it->visitAggregate(EvPreVisit, this);
 | 
						|
 | 
						|
    if (visit) {
 | 
						|
        it->incrementDepth(this);
 | 
						|
 | 
						|
        if (it->rightToLeft) {
 | 
						|
            for (TIntermSequence::reverse_iterator sit = sequence.rbegin(); sit != sequence.rend(); sit++) {
 | 
						|
                (*sit)->traverse(it);
 | 
						|
 | 
						|
                if (visit && it->inVisit) {
 | 
						|
                    if (*sit != sequence.front())
 | 
						|
                        visit = it->visitAggregate(EvInVisit, this);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) {
 | 
						|
                (*sit)->traverse(it);
 | 
						|
 | 
						|
                if (visit && it->inVisit) {
 | 
						|
                    if (*sit != sequence.back())
 | 
						|
                        visit = it->visitAggregate(EvInVisit, this);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        it->decrementDepth();
 | 
						|
    }
 | 
						|
 | 
						|
    if (visit && it->postVisit)
 | 
						|
        it->visitAggregate(EvPostVisit, this);
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// Traverse a selection node.  Same comments in binary node apply here.
 | 
						|
//
 | 
						|
void TIntermSelection::traverse(TIntermTraverser *it)
 | 
						|
{
 | 
						|
    bool visit = true;
 | 
						|
 | 
						|
    if (it->preVisit)
 | 
						|
        visit = it->visitSelection(EvPreVisit, this);
 | 
						|
 | 
						|
    if (visit) {
 | 
						|
        it->incrementDepth(this);
 | 
						|
        if (it->rightToLeft) {
 | 
						|
            if (falseBlock)
 | 
						|
                falseBlock->traverse(it);
 | 
						|
            if (trueBlock)
 | 
						|
                trueBlock->traverse(it);
 | 
						|
            condition->traverse(it);
 | 
						|
        } else {
 | 
						|
            condition->traverse(it);
 | 
						|
            if (trueBlock)
 | 
						|
                trueBlock->traverse(it);
 | 
						|
            if (falseBlock)
 | 
						|
                falseBlock->traverse(it);
 | 
						|
        }
 | 
						|
        it->decrementDepth();
 | 
						|
    }
 | 
						|
 | 
						|
    if (visit && it->postVisit)
 | 
						|
        it->visitSelection(EvPostVisit, this);
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// Traverse a loop node.  Same comments in binary node apply here.
 | 
						|
//
 | 
						|
void TIntermLoop::traverse(TIntermTraverser *it)
 | 
						|
{
 | 
						|
    bool visit = true;
 | 
						|
 | 
						|
    if (it->preVisit)
 | 
						|
        visit = it->visitLoop(EvPreVisit, this);
 | 
						|
 | 
						|
    if (visit) {
 | 
						|
        it->incrementDepth(this);
 | 
						|
 | 
						|
        if (it->rightToLeft) {
 | 
						|
            if (terminal)
 | 
						|
                terminal->traverse(it);
 | 
						|
 | 
						|
            if (body)
 | 
						|
                body->traverse(it);
 | 
						|
 | 
						|
            if (test)
 | 
						|
                test->traverse(it);
 | 
						|
        } else {
 | 
						|
            if (test)
 | 
						|
                test->traverse(it);
 | 
						|
 | 
						|
            if (body)
 | 
						|
                body->traverse(it);
 | 
						|
 | 
						|
            if (terminal)
 | 
						|
                terminal->traverse(it);
 | 
						|
        }
 | 
						|
 | 
						|
        it->decrementDepth();
 | 
						|
    }
 | 
						|
 | 
						|
    if (visit && it->postVisit)
 | 
						|
        it->visitLoop(EvPostVisit, this);
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// Traverse a branch node.  Same comments in binary node apply here.
 | 
						|
//
 | 
						|
void TIntermBranch::traverse(TIntermTraverser *it)
 | 
						|
{
 | 
						|
    bool visit = true;
 | 
						|
 | 
						|
    if (it->preVisit)
 | 
						|
        visit = it->visitBranch(EvPreVisit, this);
 | 
						|
 | 
						|
    if (visit && expression) {
 | 
						|
        it->incrementDepth(this);
 | 
						|
        expression->traverse(it);
 | 
						|
        it->decrementDepth();
 | 
						|
    }
 | 
						|
 | 
						|
    if (visit && it->postVisit)
 | 
						|
        it->visitBranch(EvPostVisit, this);
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// Traverse a switch node.
 | 
						|
//
 | 
						|
void TIntermSwitch::traverse(TIntermTraverser* it)
 | 
						|
{
 | 
						|
    bool visit = true;
 | 
						|
 | 
						|
    if (it->preVisit)
 | 
						|
        visit = it->visitSwitch(EvPreVisit, this);
 | 
						|
 | 
						|
    if (visit) {
 | 
						|
        it->incrementDepth(this);
 | 
						|
        if (it->rightToLeft) {
 | 
						|
            body->traverse(it);
 | 
						|
            condition->traverse(it);
 | 
						|
        } else {
 | 
						|
            condition->traverse(it);
 | 
						|
            body->traverse(it);
 | 
						|
        }
 | 
						|
        it->decrementDepth();
 | 
						|
    }
 | 
						|
 | 
						|
    if (visit && it->postVisit)
 | 
						|
        it->visitSwitch(EvPostVisit, this);
 | 
						|
}
 | 
						|
 | 
						|
} // end namespace glslang
 |