// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "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, TType& t)
		: error(false),
		  index(0),
		  unionArray(cUnion),
		  type(t),
		  constructorType(constructType),
		  singleConstantParam(singleConstParam),
		  infoSink(sink),
		  size(0),
		  isMatrix(false),
		  matrixRows(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*);

	size_t index;
	ConstantUnion *unionArray;
	TType type;
	TOperator constructorType;
	bool singleConstantParam;
	TInfoSink& infoSink;
	size_t size; // size of the constructor ( 4 for vec4)
	bool isMatrix;
	int matrixRows; // number of rows in 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 != EvqConstExpr) {
		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;
			matrixRows = node->getType().getSecondarySize();
		}
	}

	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;
		matrixRows = 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;
	size_t instanceSize = type.getObjectSize();
	TBasicType basicType = type.getBasicType();

	if (index >= instanceSize)
		return;

	if (!singleConstantParam) {
		size_t size = node->getType().getObjectSize();

		ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
		for(size_t i = 0; i < size; i++) {
			if (index >= instanceSize)
				return;
			leftUnionArray[index].cast(basicType, rightUnionArray[i]);

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

				leftUnionArray[i].cast(basicType, rightUnionArray[count]);

				(index)++;

				if (node->getType().getObjectSize() > 1)
					count++;
			}
		} else {  // for matrix constructors
			int count = 0;
			int element = index;
			for(size_t i = index; i < totalSize; i++) {
				if (i >= instanceSize)
					return;
				if (element - i == 0 || (i - element) % (matrixRows + 1) == 0 )
					leftUnionArray[i].cast(basicType, rightUnionArray[0]);
				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(const TSourceLoc& line, TIntermNode* root, ConstantUnion* unionArray, TOperator constructorType, TType t, bool singleConstantParam)
{
	if (root == 0)
		return false;

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

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