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

#include "ParseHelper.h"

bool ValidateSwitch::validate(TBasicType switchType, TParseContext *context,
	TIntermAggregate *statementList, const TSourceLoc &loc)
{
	ValidateSwitch validate(switchType, context);
	ASSERT(statementList);
	statementList->traverse(&validate);
	return validate.validateInternal(loc);
}

ValidateSwitch::ValidateSwitch(TBasicType switchType, TParseContext *context)
	: TIntermTraverser(true, false, true),
	  mSwitchType(switchType),
	  mContext(context),
	  mCaseTypeMismatch(false),
	  mFirstCaseFound(false),
	  mStatementBeforeCase(false),
	  mLastStatementWasCase(false),
	  mControlFlowDepth(0),
	  mCaseInsideControlFlow(false),
	  mDefaultCount(0),
	  mDuplicateCases(false)
{}

void ValidateSwitch::visitSymbol(TIntermSymbol *)
{
	if (!mFirstCaseFound)
		mStatementBeforeCase = true;
	mLastStatementWasCase = false;
}

void ValidateSwitch::visitConstantUnion(TIntermConstantUnion *)
{
	// Conditions of case labels are not traversed, so this is some other constant
	// Could be just a statement like "0;"
	if (!mFirstCaseFound)
		mStatementBeforeCase = true;
	mLastStatementWasCase = false;
}

bool ValidateSwitch::visitBinary(Visit, TIntermBinary *)
{
	if (!mFirstCaseFound)
		mStatementBeforeCase = true;
	mLastStatementWasCase = false;
	return true;
}

bool ValidateSwitch::visitUnary(Visit, TIntermUnary *)
{
	if (!mFirstCaseFound)
		mStatementBeforeCase = true;
	mLastStatementWasCase = false;
	return true;
}

bool ValidateSwitch::visitSelection(Visit visit, TIntermSelection *)
{
	if (visit == PreVisit)
		++mControlFlowDepth;
	if (visit == PostVisit)
		--mControlFlowDepth;
	if (!mFirstCaseFound)
		mStatementBeforeCase = true;
	mLastStatementWasCase = false;
	return true;
}

bool ValidateSwitch::visitSwitch(Visit, TIntermSwitch *)
{
	if (!mFirstCaseFound)
		mStatementBeforeCase = true;
	mLastStatementWasCase = false;
	// Don't go into nested switch statements
	return false;
}

bool ValidateSwitch::visitCase(Visit, TIntermCase *node)
{
	const char *nodeStr = node->hasCondition() ? "case" : "default";
	if (mControlFlowDepth > 0)
	{
		mContext->error(node->getLine(), "label statement nested inside control flow", nodeStr);
		mCaseInsideControlFlow = true;
	}
	mFirstCaseFound = true;
	mLastStatementWasCase = true;
	if (!node->hasCondition())
	{
		++mDefaultCount;
		if (mDefaultCount > 1)
		{
			mContext->error(node->getLine(), "duplicate default label", nodeStr);
		}
	}
	else
	{
		TIntermConstantUnion *condition = node->getCondition()->getAsConstantUnion();
		if (condition == nullptr)
		{
			// This can happen in error cases.
			return false;
		}
		TBasicType conditionType = condition->getBasicType();
		if (conditionType != mSwitchType)
		{
			mContext->error(condition->getLine(),
				"case label type does not match switch init-expression type", nodeStr);
			mCaseTypeMismatch = true;
		}

		if (conditionType == EbtInt)
		{
			int iConst = condition->getIConst(0);
			if (mCasesSigned.find(iConst) != mCasesSigned.end())
			{
				mContext->error(condition->getLine(), "duplicate case label", nodeStr);
				mDuplicateCases = true;
			}
			else
			{
				mCasesSigned.insert(iConst);
			}
		}
		else if (conditionType == EbtUInt)
		{
			unsigned int uConst = condition->getUConst(0);
			if (mCasesUnsigned.find(uConst) != mCasesUnsigned.end())
			{
				mContext->error(condition->getLine(), "duplicate case label", nodeStr);
				mDuplicateCases = true;
			}
			else
			{
				mCasesUnsigned.insert(uConst);
			}
		}
		// Other types are possible only in error cases, where the error has already been generated
		// when parsing the case statement.
	}
	// Don't traverse the condition of the case statement
	return false;
}

bool ValidateSwitch::visitAggregate(Visit visit, TIntermAggregate *)
{
	if (getParentNode() != nullptr)
	{
		// This is not the statementList node, but some other node.
		if (!mFirstCaseFound)
			mStatementBeforeCase = true;
		mLastStatementWasCase = false;
	}
	return true;
}

bool ValidateSwitch::visitLoop(Visit visit, TIntermLoop *)
{
	if (visit == PreVisit)
		++mControlFlowDepth;
	if (visit == PostVisit)
		--mControlFlowDepth;
	if (!mFirstCaseFound)
		mStatementBeforeCase = true;
	mLastStatementWasCase = false;
	return true;
}

bool ValidateSwitch::visitBranch(Visit, TIntermBranch *)
{
	if (!mFirstCaseFound)
		mStatementBeforeCase = true;
	mLastStatementWasCase = false;
	return true;
}

bool ValidateSwitch::validateInternal(const TSourceLoc &loc)
{
	if (mStatementBeforeCase)
	{
		mContext->error(loc,
			"statement before the first label", "switch");
	}
	if (mLastStatementWasCase)
	{
		mContext->error(loc,
			"no statement between the last label and the end of the switch statement", "switch");
	}
	return !mStatementBeforeCase && !mLastStatementWasCase && !mCaseInsideControlFlow &&
		!mCaseTypeMismatch && mDefaultCount <= 1 && !mDuplicateCases;
}
