//
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

#include "compiler/intermediate.h"

//
// 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 straighforward....
//
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(PreVisit, this);
    
    //
    // Visit the children, in the right order.
    //
    if (visit)
    {
        it->incrementDepth();

        if (it->rightToLeft) 
        {
            if (right)
                right->traverse(it);
            
            if (it->inVisit)
                visit = it->visitBinary(InVisit, this);

            if (visit && left)
                left->traverse(it);
        }
        else
        {
            if (left)
                left->traverse(it);
            
            if (it->inVisit)
                visit = it->visitBinary(InVisit, 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(PostVisit, 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(PreVisit, this);

    if (visit) {
        it->incrementDepth();
        operand->traverse(it);
        it->decrementDepth();
    }
    
    if (visit && it->postVisit)
        it->visitUnary(PostVisit, 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(PreVisit, this);
    
    if (visit)
    {
        it->incrementDepth();

        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(InVisit, 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(InVisit, this);
                }
            }
        }
        
        it->decrementDepth();
    }

    if (visit && it->postVisit)
        it->visitAggregate(PostVisit, 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(PreVisit, this);
    
    if (visit) {
        it->incrementDepth();
        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(PostVisit, 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(PreVisit, this);
    
    if (visit)
    {
        it->incrementDepth();

        if (it->rightToLeft)
        {
            if (expr)
                expr->traverse(it);

            if (body)
                body->traverse(it);

            if (cond)
                cond->traverse(it);

            if (init)
                init->traverse(it);
        }
        else
        {
            if (init)
                init->traverse(it);

            if (cond)
                cond->traverse(it);

            if (body)
                body->traverse(it);

            if (expr)
                expr->traverse(it);
        }

        it->decrementDepth();
    }

    if (visit && it->postVisit)
        it->visitLoop(PostVisit, 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(PreVisit, this);
    
    if (visit && expression) {
        it->incrementDepth();
        expression->traverse(it);
        it->decrementDepth();
    }

    if (visit && it->postVisit)
        it->visitBranch(PostVisit, this);
}

