//
// 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/ParseHelper.h"

//
// Use this class to carry along data from node to node in 
// the traversal
//
class TConstTraverser : public TIntermTraverser {
public:
    TConstTraverser(ConstantUnion* cUnion, bool singleConstParam, TOperator constructType, TInfoSink& sink, TSymbolTable& symTable, TType& t)
        : error(false),
          index(0),
          unionArray(cUnion),
          type(t),
          constructorType(constructType),
          singleConstantParam(singleConstParam),
          infoSink(sink),
          symbolTable(symTable),
          size(0),
          isMatrix(false),
          matrixSize(0) {
    }

    bool error;

protected:
    void visitSymbol(TIntermSymbol*);
    void visitConstantUnion(TIntermConstantUnion*);
    bool visitBinary(Visit visit, TIntermBinary*);
    bool visitUnary(Visit visit, TIntermUnary*);
    bool visitSelection(Visit visit, TIntermSelection*);
    bool visitAggregate(Visit visit, TIntermAggregate*);
    bool visitLoop(Visit visit, TIntermLoop*);
    bool visitBranch(Visit visit, TIntermBranch*);

    int index;
    ConstantUnion *unionArray;
    TType type;
    TOperator constructorType;
    bool singleConstantParam;
    TInfoSink& infoSink;
    TSymbolTable& symbolTable;
    int size; // size of the constructor ( 4 for vec4)
    bool isMatrix;
    int matrixSize; // dimension of the matrix (nominal size and not the instance size)
};

//
// The rest of the file are the traversal functions.  The last one
// is the one that starts the traversal.
//
// Return true from interior nodes to have the external traversal
// continue on to children.  If you process children yourself,
// return false.
//

void TConstTraverser::visitSymbol(TIntermSymbol* node)
{
    infoSink.info.message(EPrefixInternalError, "Symbol Node found in constant constructor", node->getLine());
    return;

}

bool TConstTraverser::visitBinary(Visit visit, TIntermBinary* node)
{
    TQualifier qualifier = node->getType().getQualifier();
    
    if (qualifier != EvqConst) {
        TString buf;
        buf.append("'constructor' : assigning non-constant to ");
        buf.append(type.getCompleteString());
        infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
        error = true;
        return false;  
    }

   infoSink.info.message(EPrefixInternalError, "Binary Node found in constant constructor", node->getLine());
    
    return false;
}

bool TConstTraverser::visitUnary(Visit visit, TIntermUnary* node)
{
    TString buf;
    buf.append("'constructor' : assigning non-constant to ");
    buf.append(type.getCompleteString());
    infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
    error = true;
    return false;  
}

bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
{
    if (!node->isConstructor() && node->getOp() != EOpComma) {
        TString buf;
        buf.append("'constructor' : assigning non-constant to ");
        buf.append(type.getCompleteString());
        infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
        error = true;
        return false;  
    }

    if (node->getSequence().size() == 0) {
        error = true;
        return false;
    }

    bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion();
    if (flag) 
    {
        singleConstantParam = true; 
        constructorType = node->getOp();
        size = node->getType().getObjectSize();

        if (node->getType().isMatrix()) {
            isMatrix = true;
            matrixSize = node->getType().getNominalSize();
        }
    }       

    for (TIntermSequence::iterator p = node->getSequence().begin(); 
                                   p != node->getSequence().end(); p++) {

        if (node->getOp() == EOpComma)
            index = 0;           

        (*p)->traverse(this);
    }   
    if (flag) 
    {
        singleConstantParam = false;   
        constructorType = EOpNull;
        size = 0;
        isMatrix = false;
        matrixSize = 0;
    }
    return false;
}

bool TConstTraverser::visitSelection(Visit visit, TIntermSelection* node)
{
    infoSink.info.message(EPrefixInternalError, "Selection Node found in constant constructor", node->getLine());
    error = true;
    return false;
}

void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
{
    if (!node->getUnionArrayPointer())
    {
        // The constant was not initialized, this should already have been logged
        assert(infoSink.info.size() != 0);
        return;
    }

    ConstantUnion* leftUnionArray = unionArray;
    int instanceSize = type.getObjectSize();

    if (index >= instanceSize)
        return;

    if (!singleConstantParam) {
        int size = node->getType().getObjectSize();
    
        ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
        for (int i=0; i < size; i++) {
            if (index >= instanceSize)
                return;
            leftUnionArray[index] = rightUnionArray[i];

            (index)++;
        }
    } else {
        int totalSize = index + size;
        ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
        if (!isMatrix) {
            int count = 0;
            for (int i = index; i < totalSize; i++) {
                if (i >= instanceSize)
                    return;

                leftUnionArray[i] = rightUnionArray[count];

                (index)++;
                
                if (node->getType().getObjectSize() > 1)
                    count++;
            }
        } else {  // for matrix constructors
            int count = 0;
            int element = index;
            for (int i = index; i < totalSize; i++) {
                if (i >= instanceSize)
                    return;
                if (element - i == 0 || (i - element) % (matrixSize + 1) == 0 )
                    leftUnionArray[i] = rightUnionArray[count];
                else 
                    leftUnionArray[i].setFConst(0.0f);

                (index)++;

                if (node->getType().getObjectSize() > 1)
                    count++;                
            }
        }
    }
}

bool TConstTraverser::visitLoop(Visit visit, TIntermLoop* node)
{
    infoSink.info.message(EPrefixInternalError, "Loop Node found in constant constructor", node->getLine());
    error = true;
    return false;
}

bool TConstTraverser::visitBranch(Visit visit, TIntermBranch* node)
{
    infoSink.info.message(EPrefixInternalError, "Branch Node found in constant constructor", node->getLine());
    error = true;
    return false;
}

//
// This function is the one to call externally to start the traversal.
// Individual functions can be initialized to 0 to skip processing of that
// type of node.  It's children will still be processed.
//
bool TIntermediate::parseConstTree(TSourceLoc line, TIntermNode* root, ConstantUnion* unionArray, TOperator constructorType, TSymbolTable& symbolTable, TType t, bool singleConstantParam)
{
    if (root == 0)
        return false;

    TConstTraverser it(unionArray, singleConstantParam, constructorType, infoSink, symbolTable, t);

    root->traverse(&it);
    if (it.error)
        return true;
    else
        return false;
}
