//
//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 cancelled 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
