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

#include <limits>
#include <stdarg.h>
#include <stdio.h>

#include "glslang.h"
#include "preprocessor/SourceLocation.h"
#include "ValidateSwitch.h"

///////////////////////////////////////////////////////////////////////
//
// Sub- vector and matrix fields
//
////////////////////////////////////////////////////////////////////////

namespace
{
	bool IsVaryingOut(TQualifier qualifier)
	{
		switch(qualifier)
		{
		case EvqVaryingOut:
		case EvqSmoothOut:
		case EvqFlatOut:
		case EvqCentroidOut:
		case EvqVertexOut:
			return true;

		default: break;
		}

		return false;
	}

	bool IsVaryingIn(TQualifier qualifier)
	{
		switch(qualifier)
		{
		case EvqVaryingIn:
		case EvqSmoothIn:
		case EvqFlatIn:
		case EvqCentroidIn:
		case EvqFragmentIn:
			return true;

		default: break;
		}

		return false;
	}

	bool IsVarying(TQualifier qualifier)
	{
		return IsVaryingIn(qualifier) || IsVaryingOut(qualifier);
	}

	bool IsAssignment(TOperator op)
	{
		switch(op)
		{
		case EOpPostIncrement:
		case EOpPostDecrement:
		case EOpPreIncrement:
		case EOpPreDecrement:
		case EOpAssign:
		case EOpAddAssign:
		case EOpSubAssign:
		case EOpMulAssign:
		case EOpVectorTimesMatrixAssign:
		case EOpVectorTimesScalarAssign:
		case EOpMatrixTimesScalarAssign:
		case EOpMatrixTimesMatrixAssign:
		case EOpDivAssign:
		case EOpIModAssign:
		case EOpBitShiftLeftAssign:
		case EOpBitShiftRightAssign:
		case EOpBitwiseAndAssign:
		case EOpBitwiseXorAssign:
		case EOpBitwiseOrAssign:
			return true;
		default:
			return false;
		}
	}
}

//
// Look at a '.' field selector string and change it into offsets
// for a vector.
//
bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, const TSourceLoc &line)
{
	fields.num = (int) compString.size();
	if (fields.num > 4) {
		error(line, "illegal vector field selection", compString.c_str());
		return false;
	}

	enum {
		exyzw,
		ergba,
		estpq
	} fieldSet[4];

	for (int i = 0; i < fields.num; ++i) {
		switch (compString[i])  {
		case 'x':
			fields.offsets[i] = 0;
			fieldSet[i] = exyzw;
			break;
		case 'r':
			fields.offsets[i] = 0;
			fieldSet[i] = ergba;
			break;
		case 's':
			fields.offsets[i] = 0;
			fieldSet[i] = estpq;
			break;
		case 'y':
			fields.offsets[i] = 1;
			fieldSet[i] = exyzw;
			break;
		case 'g':
			fields.offsets[i] = 1;
			fieldSet[i] = ergba;
			break;
		case 't':
			fields.offsets[i] = 1;
			fieldSet[i] = estpq;
			break;
		case 'z':
			fields.offsets[i] = 2;
			fieldSet[i] = exyzw;
			break;
		case 'b':
			fields.offsets[i] = 2;
			fieldSet[i] = ergba;
			break;
		case 'p':
			fields.offsets[i] = 2;
			fieldSet[i] = estpq;
			break;
		case 'w':
			fields.offsets[i] = 3;
			fieldSet[i] = exyzw;
			break;
		case 'a':
			fields.offsets[i] = 3;
			fieldSet[i] = ergba;
			break;
		case 'q':
			fields.offsets[i] = 3;
			fieldSet[i] = estpq;
			break;
		default:
			error(line, "illegal vector field selection", compString.c_str());
			return false;
		}
	}

	for (int i = 0; i < fields.num; ++i) {
		if (fields.offsets[i] >= vecSize) {
			error(line, "vector field selection out of range",  compString.c_str());
			return false;
		}

		if (i > 0) {
			if (fieldSet[i] != fieldSet[i-1]) {
				error(line, "illegal - vector component fields not from the same set", compString.c_str());
				return false;
			}
		}
	}

	return true;
}

///////////////////////////////////////////////////////////////////////
//
// Errors
//
////////////////////////////////////////////////////////////////////////

//
// Track whether errors have occurred.
//
void TParseContext::recover()
{
}

//
// Used by flex/bison to output all syntax and parsing errors.
//
void TParseContext::error(const TSourceLoc& loc,
						  const char* reason, const char* token,
						  const char* extraInfo)
{
	pp::SourceLocation srcLoc(loc.first_file, loc.first_line);
	mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR,
						   srcLoc, reason, token, extraInfo);

}

void TParseContext::warning(const TSourceLoc& loc,
							const char* reason, const char* token,
							const char* extraInfo) {
	pp::SourceLocation srcLoc(loc.first_file, loc.first_line);
	mDiagnostics.writeInfo(pp::Diagnostics::PP_WARNING,
						   srcLoc, reason, token, extraInfo);
}

void TParseContext::trace(const char* str)
{
	mDiagnostics.writeDebug(str);
}

//
// Same error message for all places assignments don't work.
//
void TParseContext::assignError(const TSourceLoc &line, const char* op, TString left, TString right)
{
	std::stringstream extraInfoStream;
	extraInfoStream << "cannot convert from '" << right << "' to '" << left << "'";
	std::string extraInfo = extraInfoStream.str();
	error(line, "", op, extraInfo.c_str());
}

//
// Same error message for all places unary operations don't work.
//
void TParseContext::unaryOpError(const TSourceLoc &line, const char* op, TString operand)
{
	std::stringstream extraInfoStream;
	extraInfoStream << "no operation '" << op << "' exists that takes an operand of type " << operand
					<< " (or there is no acceptable conversion)";
	std::string extraInfo = extraInfoStream.str();
	error(line, " wrong operand type", op, extraInfo.c_str());
}

//
// Same error message for all binary operations don't work.
//
void TParseContext::binaryOpError(const TSourceLoc &line, const char* op, TString left, TString right)
{
	std::stringstream extraInfoStream;
	extraInfoStream << "no operation '" << op << "' exists that takes a left-hand operand of type '" << left
					<< "' and a right operand of type '" << right << "' (or there is no acceptable conversion)";
	std::string extraInfo = extraInfoStream.str();
	error(line, " wrong operand types ", op, extraInfo.c_str());
}

bool TParseContext::precisionErrorCheck(const TSourceLoc &line, TPrecision precision, TBasicType type){
	if (!mChecksPrecisionErrors)
		return false;
	switch( type ){
	case EbtFloat:
		if( precision == EbpUndefined ){
			error( line, "No precision specified for (float)", "" );
			return true;
		}
		break;
	case EbtInt:
		if( precision == EbpUndefined ){
			error( line, "No precision specified (int)", "" );
			return true;
		}
		break;
	default:
		return false;
	}
	return false;
}

//
// Both test and if necessary, spit out an error, to see if the node is really
// an l-value that can be operated on this way.
//
// Returns true if the was an error.
//
bool TParseContext::lValueErrorCheck(const TSourceLoc &line, const char* op, TIntermTyped* node)
{
	TIntermSymbol* symNode = node->getAsSymbolNode();
	TIntermBinary* binaryNode = node->getAsBinaryNode();

	if (binaryNode) {
		bool errorReturn;

		switch(binaryNode->getOp()) {
		case EOpIndexDirect:
		case EOpIndexIndirect:
		case EOpIndexDirectStruct:
			return lValueErrorCheck(line, op, binaryNode->getLeft());
		case EOpVectorSwizzle:
			errorReturn = lValueErrorCheck(line, op, binaryNode->getLeft());
			if (!errorReturn) {
				int offset[4] = {0,0,0,0};

				TIntermTyped* rightNode = binaryNode->getRight();
				TIntermAggregate *aggrNode = rightNode->getAsAggregate();

				for (TIntermSequence::iterator p = aggrNode->getSequence().begin();
											   p != aggrNode->getSequence().end(); p++) {
					int value = (*p)->getAsTyped()->getAsConstantUnion()->getIConst(0);
					offset[value]++;
					if (offset[value] > 1) {
						error(line, " l-value of swizzle cannot have duplicate components", op);

						return true;
					}
				}
			}

			return errorReturn;
		case EOpIndexDirectInterfaceBlock:
		default:
			break;
		}
		error(line, " l-value required", op);

		return true;
	}


	const char* symbol = 0;
	if (symNode != 0)
		symbol = symNode->getSymbol().c_str();

	const char* message = 0;
	switch (node->getQualifier()) {
	case EvqConstExpr:      message = "can't modify a const";        break;
	case EvqConstReadOnly:  message = "can't modify a const";        break;
	case EvqAttribute:      message = "can't modify an attribute";   break;
	case EvqFragmentIn:     message = "can't modify an input";       break;
	case EvqVertexIn:       message = "can't modify an input";       break;
	case EvqUniform:        message = "can't modify a uniform";      break;
	case EvqSmoothIn:
	case EvqFlatIn:
	case EvqCentroidIn:
	case EvqVaryingIn:      message = "can't modify a varying";      break;
	case EvqInput:          message = "can't modify an input";       break;
	case EvqFragCoord:      message = "can't modify gl_FragCoord";   break;
	case EvqFrontFacing:    message = "can't modify gl_FrontFacing"; break;
	case EvqPointCoord:     message = "can't modify gl_PointCoord";  break;
	case EvqInstanceID:     message = "can't modify gl_InstanceID";  break;
	case EvqVertexID:       message = "can't modify gl_VertexID";    break;
	default:

		//
		// Type that can't be written to?
		//
		if(IsSampler(node->getBasicType()))
		{
			message = "can't modify a sampler";
		}
		else if(node->getBasicType() == EbtVoid)
		{
			message = "can't modify void";
		}
	}

	if (message == 0 && binaryNode == 0 && symNode == 0) {
		error(line, " l-value required", op);

		return true;
	}


	//
	// Everything else is okay, no error.
	//
	if (message == 0)
		return false;

	//
	// If we get here, we have an error and a message.
	//
	if (symNode) {
		std::stringstream extraInfoStream;
		extraInfoStream << "\"" << symbol << "\" (" << message << ")";
		std::string extraInfo = extraInfoStream.str();
		error(line, " l-value required", op, extraInfo.c_str());
	}
	else {
		std::stringstream extraInfoStream;
		extraInfoStream << "(" << message << ")";
		std::string extraInfo = extraInfoStream.str();
		error(line, " l-value required", op, extraInfo.c_str());
	}

	return true;
}

//
// Both test, and if necessary spit out an error, to see if the node is really
// a constant.
//
// Returns true if the was an error.
//
bool TParseContext::constErrorCheck(TIntermTyped* node)
{
	if (node->getQualifier() == EvqConstExpr)
		return false;

	error(node->getLine(), "constant expression required", "");

	return true;
}

//
// Both test, and if necessary spit out an error, to see if the node is really
// an integer.
//
// Returns true if the was an error.
//
bool TParseContext::integerErrorCheck(TIntermTyped* node, const char* token)
{
	if (node->isScalarInt())
		return false;

	error(node->getLine(), "integer expression required", token);

	return true;
}

//
// Both test, and if necessary spit out an error, to see if we are currently
// globally scoped.
//
// Returns true if the was an error.
//
bool TParseContext::globalErrorCheck(const TSourceLoc &line, bool global, const char* token)
{
	if (global)
		return false;

	error(line, "only allowed at global scope", token);

	return true;
}

//
// For now, keep it simple:  if it starts "gl_", it's reserved, independent
// of scope.  Except, if the symbol table is at the built-in push-level,
// which is when we are parsing built-ins.
// Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a
// webgl shader.
//
// Returns true if there was an error.
//
bool TParseContext::reservedErrorCheck(const TSourceLoc &line, const TString& identifier)
{
	static const char* reservedErrMsg = "reserved built-in name";
	if (!symbolTable.atBuiltInLevel()) {
		if (identifier.compare(0, 3, "gl_") == 0) {
			error(line, reservedErrMsg, "gl_");
			return true;
		}
		if (identifier.find("__") != TString::npos) {
			error(line, "identifiers containing two consecutive underscores (__) are reserved as possible future keywords", identifier.c_str());
			return true;
		}
	}

	return false;
}

//
// Make sure there is enough data provided to the constructor to build
// something of the type of the constructor.  Also returns the type of
// the constructor.
//
// Returns true if there was an error in construction.
//
bool TParseContext::constructorErrorCheck(const TSourceLoc &line, TIntermNode* node, TFunction& function, TOperator op, TType* type)
{
	*type = function.getReturnType();

	bool constructingMatrix = false;
	switch(op) {
	case EOpConstructMat2:
	case EOpConstructMat2x3:
	case EOpConstructMat2x4:
	case EOpConstructMat3x2:
	case EOpConstructMat3:
	case EOpConstructMat3x4:
	case EOpConstructMat4x2:
	case EOpConstructMat4x3:
	case EOpConstructMat4:
		constructingMatrix = true;
		break;
	default:
		break;
	}

	//
	// Note: It's okay to have too many components available, but not okay to have unused
	// arguments.  'full' will go to true when enough args have been seen.  If we loop
	// again, there is an extra argument, so 'overfull' will become true.
	//

	size_t size = 0;
	bool full = false;
	bool overFull = false;
	bool matrixInMatrix = false;
	bool arrayArg = false;
	for (size_t i = 0; i < function.getParamCount(); ++i) {
		const TParameter& param = function.getParam(i);
		size += param.type->getObjectSize();

		if (constructingMatrix && param.type->isMatrix())
			matrixInMatrix = true;
		if (full)
			overFull = true;
		if (op != EOpConstructStruct && !type->isArray() && size >= type->getObjectSize())
			full = true;
		if (param.type->isArray())
			arrayArg = true;
	}

	if(type->isArray()) {
		if(type->getArraySize() == 0) {
			type->setArraySize(function.getParamCount());
		} else if(type->getArraySize() != (int)function.getParamCount()) {
			error(line, "array constructor needs one argument per array element", "constructor");
			return true;
		}
	}

	if (arrayArg && op != EOpConstructStruct) {
		error(line, "constructing from a non-dereferenced array", "constructor");
		return true;
	}

	if (matrixInMatrix && !type->isArray()) {
		if (function.getParamCount() != 1) {
		  error(line, "constructing matrix from matrix can only take one argument", "constructor");
		  return true;
		}
	}

	if (overFull) {
		error(line, "too many arguments", "constructor");
		return true;
	}

	if (op == EOpConstructStruct && !type->isArray() && type->getStruct()->fields().size() != function.getParamCount()) {
		error(line, "Number of constructor parameters does not match the number of structure fields", "constructor");
		return true;
	}

	if (!type->isMatrix() || !matrixInMatrix) {
		if ((op != EOpConstructStruct && size != 1 && size < type->getObjectSize()) ||
			(op == EOpConstructStruct && size < type->getObjectSize())) {
			error(line, "not enough data provided for construction", "constructor");
			return true;
		}
	}

	TIntermTyped *typed = node ? node->getAsTyped() : 0;
	if (typed == 0) {
		error(line, "constructor argument does not have a type", "constructor");
		return true;
	}
	if (op != EOpConstructStruct && IsSampler(typed->getBasicType())) {
		error(line, "cannot convert a sampler", "constructor");
		return true;
	}
	if (typed->getBasicType() == EbtVoid) {
		error(line, "cannot convert a void", "constructor");
		return true;
	}

	return false;
}

// This function checks to see if a void variable has been declared and raise an error message for such a case
//
// returns true in case of an error
//
bool TParseContext::voidErrorCheck(const TSourceLoc &line, const TString& identifier, const TBasicType& type)
{
	if(type == EbtVoid) {
		error(line, "illegal use of type 'void'", identifier.c_str());
		return true;
	}

	return false;
}

// This function checks to see if the node (for the expression) contains a scalar boolean expression or not
//
// returns true in case of an error
//
bool TParseContext::boolErrorCheck(const TSourceLoc &line, const TIntermTyped* type)
{
	if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) {
		error(line, "boolean expression expected", "");
		return true;
	}

	return false;
}

// This function checks to see if the node (for the expression) contains a scalar boolean expression or not
//
// returns true in case of an error
//
bool TParseContext::boolErrorCheck(const TSourceLoc &line, const TPublicType& pType)
{
	if (pType.type != EbtBool || pType.array || (pType.primarySize > 1) || (pType.secondarySize > 1)) {
		error(line, "boolean expression expected", "");
		return true;
	}

	return false;
}

bool TParseContext::samplerErrorCheck(const TSourceLoc &line, const TPublicType& pType, const char* reason)
{
	if (pType.type == EbtStruct) {
		if (containsSampler(*pType.userDef)) {
			error(line, reason, getBasicString(pType.type), "(structure contains a sampler)");

			return true;
		}

		return false;
	} else if (IsSampler(pType.type)) {
		error(line, reason, getBasicString(pType.type));

		return true;
	}

	return false;
}

bool TParseContext::structQualifierErrorCheck(const TSourceLoc &line, const TPublicType& pType)
{
	switch(pType.qualifier)
	{
	case EvqVaryingOut:
	case EvqSmooth:
	case EvqFlat:
	case EvqCentroidOut:
	case EvqVaryingIn:
	case EvqSmoothIn:
	case EvqFlatIn:
	case EvqCentroidIn:
	case EvqAttribute:
	case EvqVertexIn:
	case EvqFragmentOut:
		if(pType.type == EbtStruct)
		{
			error(line, "cannot be used with a structure", getQualifierString(pType.qualifier));

			return true;
		}
		break;
	default:
		break;
	}

	if (pType.qualifier != EvqUniform && samplerErrorCheck(line, pType, "samplers must be uniform"))
		return true;

	// check for layout qualifier issues
	if (pType.qualifier != EvqVertexIn && pType.qualifier != EvqFragmentOut &&
		layoutLocationErrorCheck(line, pType.layoutQualifier))
	{
		return true;
	}

	return false;
}

// These checks are common for all declarations starting a declarator list, and declarators that follow an empty
// declaration.
//
bool TParseContext::singleDeclarationErrorCheck(const TPublicType &publicType, const TSourceLoc &identifierLocation)
{
	switch(publicType.qualifier)
	{
	case EvqVaryingIn:
	case EvqVaryingOut:
	case EvqAttribute:
	case EvqVertexIn:
	case EvqFragmentOut:
		if(publicType.type == EbtStruct)
		{
			error(identifierLocation, "cannot be used with a structure",
				getQualifierString(publicType.qualifier));
			return true;
		}

	default: break;
	}

	if(publicType.qualifier != EvqUniform && samplerErrorCheck(identifierLocation, publicType,
		"samplers must be uniform"))
	{
		return true;
	}

	// check for layout qualifier issues
	const TLayoutQualifier layoutQualifier = publicType.layoutQualifier;

	if(layoutQualifier.matrixPacking != EmpUnspecified)
	{
		error(identifierLocation, "layout qualifier", getMatrixPackingString(layoutQualifier.matrixPacking),
			"only valid for interface blocks");
		return true;
	}

	if(layoutQualifier.blockStorage != EbsUnspecified)
	{
		error(identifierLocation, "layout qualifier", getBlockStorageString(layoutQualifier.blockStorage),
			"only valid for interface blocks");
		return true;
	}

	if(publicType.qualifier != EvqVertexIn && publicType.qualifier != EvqFragmentOut &&
		layoutLocationErrorCheck(identifierLocation, publicType.layoutQualifier))
	{
		return true;
	}

	return false;
}

bool TParseContext::layoutLocationErrorCheck(const TSourceLoc &location, const TLayoutQualifier &layoutQualifier)
{
	if(layoutQualifier.location != -1)
	{
		error(location, "invalid layout qualifier:", "location", "only valid on program inputs and outputs");
		return true;
	}

	return false;
}

bool TParseContext::locationDeclaratorListCheck(const TSourceLoc& line, const TPublicType &pType)
{
	if(pType.layoutQualifier.location != -1)
	{
		error(line, "location must only be specified for a single input or output variable", "location");
		return true;
	}

	return false;
}

bool TParseContext::parameterSamplerErrorCheck(const TSourceLoc &line, TQualifier qualifier, const TType& type)
{
	if ((qualifier == EvqOut || qualifier == EvqInOut) &&
			 type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) {
		error(line, "samplers cannot be output parameters", type.getBasicString());
		return true;
	}

	return false;
}

bool TParseContext::containsSampler(TType& type)
{
	if (IsSampler(type.getBasicType()))
		return true;

	if (type.getBasicType() == EbtStruct || type.isInterfaceBlock()) {
		for(const auto &field : type.getStruct()->fields()) {
			if (containsSampler(*(field->type())))
				return true;
		}
	}

	return false;
}

//
// Do size checking for an array type's size.
//
// Returns true if there was an error.
//
bool TParseContext::arraySizeErrorCheck(const TSourceLoc &line, TIntermTyped* expr, int& size)
{
	TIntermConstantUnion* constant = expr->getAsConstantUnion();

	if (expr->getQualifier() != EvqConstExpr || constant == 0 || !constant->isScalarInt())
	{
		error(line, "array size must be a constant integer expression", "");
		return true;
	}

	if (constant->getBasicType() == EbtUInt)
	{
		unsigned int uintSize = constant->getUConst(0);
		if (uintSize > static_cast<unsigned int>(std::numeric_limits<int>::max()))
		{
			error(line, "array size too large", "");
			size = 1;
			return true;
		}

		size = static_cast<int>(uintSize);
	}
	else
	{
		size = constant->getIConst(0);

		if (size < 0)
		{
			error(line, "array size must be non-negative", "");
			size = 1;
			return true;
		}
	}

	if(size == 0)
	{
		error(line, "array size must be greater than zero", "");
		return true;
	}

	return false;
}

//
// See if this qualifier can be an array.
//
// Returns true if there is an error.
//
bool TParseContext::arrayQualifierErrorCheck(const TSourceLoc &line, TPublicType type)
{
	if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqVertexIn) || (type.qualifier == EvqConstExpr && mShaderVersion < 300)) {
		error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str());
		return true;
	}

	return false;
}

//
// See if this type can be an array.
//
// Returns true if there is an error.
//
bool TParseContext::arrayTypeErrorCheck(const TSourceLoc &line, TPublicType type)
{
	//
	// Can the type be an array?
	//
	if (type.array) {
		error(line, "cannot declare arrays of arrays", TType(type).getCompleteString().c_str());
		return true;
	}

	// In ESSL1.00 shaders, structs cannot be varying (section 4.3.5). This is checked elsewhere.
	// In ESSL3.00 shaders, struct inputs/outputs are allowed but not arrays of structs (section 4.3.4).
	if(mShaderVersion >= 300 && type.type == EbtStruct && IsVarying(type.qualifier))
	{
		error(line, "cannot declare arrays of structs of this qualifier",
		      TType(type).getCompleteString().c_str());
		return true;
	}

	return false;
}

bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size, bool updateFlag, const TSourceLoc &line)
{
	bool builtIn = false;
	TSymbol* symbol = symbolTable.find(node->getSymbol(), mShaderVersion, &builtIn);
	if (symbol == 0) {
		error(line, " undeclared identifier", node->getSymbol().c_str());
		return true;
	}
	TVariable* variable = static_cast<TVariable*>(symbol);

	type->setArrayInformationType(variable->getArrayInformationType());
	variable->updateArrayInformationType(type);

	// special casing to test index value of gl_FragData. If the accessed index is >= gl_MaxDrawBuffers
	// its an error
	if (node->getSymbol() == "gl_FragData") {
		TSymbol* fragData = symbolTable.find("gl_MaxDrawBuffers", mShaderVersion, &builtIn);
		ASSERT(fragData);

		int fragDataValue = static_cast<TVariable*>(fragData)->getConstPointer()[0].getIConst();
		if (fragDataValue <= size) {
			error(line, "", "[", "gl_FragData can only have a max array size of up to gl_MaxDrawBuffers");
			return true;
		}
	}

	// we dont want to update the maxArraySize when this flag is not set, we just want to include this
	// node type in the chain of node types so that its updated when a higher maxArraySize comes in.
	if (!updateFlag)
		return false;

	size++;
	variable->getType().setMaxArraySize(size);
	type->setMaxArraySize(size);
	TType* tt = type;

	while(tt->getArrayInformationType() != 0) {
		tt = tt->getArrayInformationType();
		tt->setMaxArraySize(size);
	}

	return false;
}

//
// Enforce non-initializer type/qualifier rules.
//
// Returns true if there was an error.
//
bool TParseContext::nonInitConstErrorCheck(const TSourceLoc &line, TString& identifier, TPublicType& type, bool array)
{
	if (type.qualifier == EvqConstExpr)
	{
		// Make the qualifier make sense.
		type.qualifier = EvqTemporary;

		if (array)
		{
			error(line, "arrays may not be declared constant since they cannot be initialized", identifier.c_str());
		}
		else if (type.isStructureContainingArrays())
		{
			error(line, "structures containing arrays may not be declared constant since they cannot be initialized", identifier.c_str());
		}
		else
		{
			error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
		}

		return true;
	}

	return false;
}

//
// Do semantic checking for a variable declaration that has no initializer,
// and update the symbol table.
//
// Returns true if there was an error.
//
bool TParseContext::nonInitErrorCheck(const TSourceLoc &line, const TString& identifier, TPublicType& type)
{
	if(type.qualifier == EvqConstExpr)
	{
		// Make the qualifier make sense.
		type.qualifier = EvqTemporary;

		// Generate informative error messages for ESSL1.
		// In ESSL3 arrays and structures containing arrays can be constant.
		if(mShaderVersion < 300 && type.isStructureContainingArrays())
		{
			error(line,
				"structures containing arrays may not be declared constant since they cannot be initialized",
				identifier.c_str());
		}
		else
		{
			error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
		}

		return true;
	}
	if(type.isUnsizedArray())
	{
		error(line, "implicitly sized arrays need to be initialized", identifier.c_str());
		return true;
	}
	return false;
}

// Do some simple checks that are shared between all variable declarations,
// and update the symbol table.
//
// Returns true if declaring the variable succeeded.
//
bool TParseContext::declareVariable(const TSourceLoc &line, const TString &identifier, const TType &type,
	TVariable **variable)
{
	ASSERT((*variable) == nullptr);

	// gl_LastFragData may be redeclared with a new precision qualifier
	if(type.isArray() && identifier.compare(0, 15, "gl_LastFragData") == 0)
	{
		const TVariable *maxDrawBuffers =
			static_cast<const TVariable *>(symbolTable.findBuiltIn("gl_MaxDrawBuffers", mShaderVersion));
		if(type.getArraySize() != maxDrawBuffers->getConstPointer()->getIConst())
		{
			error(line, "redeclaration of gl_LastFragData with size != gl_MaxDrawBuffers", identifier.c_str());
			return false;
		}
	}

	if(reservedErrorCheck(line, identifier))
		return false;

	(*variable) = new TVariable(&identifier, type);
	if(!symbolTable.declare(*variable))
	{
		error(line, "redefinition", identifier.c_str());
		delete (*variable);
		(*variable) = nullptr;
		return false;
	}

	if(voidErrorCheck(line, identifier, type.getBasicType()))
		return false;

	return true;
}

bool TParseContext::paramErrorCheck(const TSourceLoc &line, TQualifier qualifier, TQualifier paramQualifier, TType* type)
{
	if (qualifier != EvqConstReadOnly && qualifier != EvqTemporary) {
		error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier));
		return true;
	}
	if (qualifier == EvqConstReadOnly && paramQualifier != EvqIn) {
		error(line, "qualifier not allowed with ", getQualifierString(qualifier), getQualifierString(paramQualifier));
		return true;
	}

	if (qualifier == EvqConstReadOnly)
		type->setQualifier(EvqConstReadOnly);
	else
		type->setQualifier(paramQualifier);

	return false;
}

bool TParseContext::extensionErrorCheck(const TSourceLoc &line, const TString& extension)
{
	const TExtensionBehavior& extBehavior = extensionBehavior();
	TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str());
	if (iter == extBehavior.end()) {
		error(line, "extension", extension.c_str(), "is not supported");
		return true;
	}
	// In GLSL ES, an extension's default behavior is "disable".
	if (iter->second == EBhDisable || iter->second == EBhUndefined) {
		error(line, "extension", extension.c_str(), "is disabled");
		return true;
	}
	if (iter->second == EBhWarn) {
		warning(line, "extension", extension.c_str(), "is being used");
		return false;
	}

	return false;
}

bool TParseContext::functionCallLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *aggregate)
{
	for(size_t i = 0; i < fnCandidate->getParamCount(); ++i)
	{
		TQualifier qual = fnCandidate->getParam(i).type->getQualifier();
		if(qual == EvqOut || qual == EvqInOut)
		{
			TIntermTyped *node = (aggregate->getSequence())[i]->getAsTyped();
			if(lValueErrorCheck(node->getLine(), "assign", node))
			{
				error(node->getLine(),
					"Constant value cannot be passed for 'out' or 'inout' parameters.", "Error");
				recover();
				return true;
			}
		}
	}
	return false;
}

void TParseContext::es3InvariantErrorCheck(const TQualifier qualifier, const TSourceLoc &invariantLocation)
{
	switch(qualifier)
	{
	case EvqVaryingOut:
	case EvqSmoothOut:
	case EvqFlatOut:
	case EvqCentroidOut:
	case EvqVertexOut:
	case EvqFragmentOut:
		break;
	default:
		error(invariantLocation, "Only out variables can be invariant.", "invariant");
		recover();
		break;
	}
}

bool TParseContext::supportsExtension(const char* extension)
{
	const TExtensionBehavior& extbehavior = extensionBehavior();
	TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
	return (iter != extbehavior.end());
}

void TParseContext::handleExtensionDirective(const TSourceLoc &line, const char* extName, const char* behavior)
{
	pp::SourceLocation loc(line.first_file, line.first_line);
	mDirectiveHandler.handleExtension(loc, extName, behavior);
}

void TParseContext::handlePragmaDirective(const TSourceLoc &line, const char* name, const char* value, bool stdgl)
{
	pp::SourceLocation loc(line.first_file, line.first_line);
	mDirectiveHandler.handlePragma(loc, name, value, stdgl);
}

/////////////////////////////////////////////////////////////////////////////////
//
// Non-Errors.
//
/////////////////////////////////////////////////////////////////////////////////

const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location,
	const TString *name,
	const TSymbol *symbol)
{
	const TVariable *variable = nullptr;

	if(!symbol)
	{
		error(location, "undeclared identifier", name->c_str());
		recover();
	}
	else if(!symbol->isVariable())
	{
		error(location, "variable expected", name->c_str());
		recover();
	}
	else
	{
		variable = static_cast<const TVariable*>(symbol);

		if(symbolTable.findBuiltIn(variable->getName(), mShaderVersion))
		{
			recover();
		}

		// Reject shaders using both gl_FragData and gl_FragColor
		TQualifier qualifier = variable->getType().getQualifier();
		if(qualifier == EvqFragData)
		{
			mUsesFragData = true;
		}
		else if(qualifier == EvqFragColor)
		{
			mUsesFragColor = true;
		}

		// This validation is not quite correct - it's only an error to write to
		// both FragData and FragColor. For simplicity, and because users shouldn't
		// be rewarded for reading from undefined variables, return an error
		// if they are both referenced, rather than assigned.
		if(mUsesFragData && mUsesFragColor)
		{
			error(location, "cannot use both gl_FragData and gl_FragColor", name->c_str());
			recover();
		}
	}

	if(!variable)
	{
		TType type(EbtFloat, EbpUndefined);
		TVariable *fakeVariable = new TVariable(name, type);
		symbolTable.declare(fakeVariable);
		variable = fakeVariable;
	}

	return variable;
}

//
// Look up a function name in the symbol table, and make sure it is a function.
//
// Return the function symbol if found, otherwise 0.
//
const TFunction* TParseContext::findFunction(const TSourceLoc &line, TFunction* call, bool *builtIn)
{
	// First find by unmangled name to check whether the function name has been
	// hidden by a variable name or struct typename.
	const TSymbol* symbol = symbolTable.find(call->getName(), mShaderVersion, builtIn);
	if (!symbol || symbol->isFunction()) {
		symbol = symbolTable.find(call->getMangledName(), mShaderVersion, builtIn);
	}

	if (!symbol) {
		error(line, "no matching overloaded function found", call->getName().c_str());
		return nullptr;
	}

	if (!symbol->isFunction()) {
		error(line, "function name expected", call->getName().c_str());
		return nullptr;
	}

	return static_cast<const TFunction*>(symbol);
}

//
// Initializers show up in several places in the grammar.  Have one set of
// code to handle them here.
//
bool TParseContext::executeInitializer(const TSourceLoc& line, const TString& identifier, const TPublicType& pType,
									   TIntermTyped *initializer, TIntermNode **intermNode)
{
	ASSERT(intermNode != nullptr);
	TType type = TType(pType);

	if(type.isUnsizedArray())
	{
		// We have not checked yet whether the initializer actually is an array or not.
		if(initializer->isArray())
		{
			type.setArraySize(initializer->getArraySize());
		}
		else
		{
			// Having a non-array initializer for an unsized array will result in an error later,
			// so we don't generate an error message here.
			type.setArraySize(1u);
		}
	}

	TVariable *variable = nullptr;
	if(!declareVariable(line, identifier, type, &variable))
	{
		return true;
	}

	if(symbolTable.atGlobalLevel() && initializer->getQualifier() != EvqConstExpr)
	{
		error(line, "global variable initializers must be constant expressions", "=");
		return true;
	}

	//
	// identifier must be of type constant, a global, or a temporary
	//
	TQualifier qualifier = type.getQualifier();
	if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConstExpr)) {
		error(line, " cannot initialize this type of qualifier ", variable->getType().getQualifierString());
		return true;
	}
	//
	// test for and propagate constant
	//

	if (qualifier == EvqConstExpr) {
		if (qualifier != initializer->getQualifier()) {
			std::stringstream extraInfoStream;
			extraInfoStream << "'" << variable->getType().getCompleteString() << "'";
			std::string extraInfo = extraInfoStream.str();
			error(line, " assigning non-constant to", "=", extraInfo.c_str());
			variable->getType().setQualifier(EvqTemporary);
			return true;
		}

		if (type != initializer->getType()) {
			error(line, " non-matching types for const initializer ",
				variable->getType().getQualifierString());
			variable->getType().setQualifier(EvqTemporary);
			return true;
		}

		if (initializer->getAsConstantUnion()) {
			variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
		} else if (initializer->getAsSymbolNode()) {
			const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol(), 0);
			const TVariable* tVar = static_cast<const TVariable*>(symbol);

			ConstantUnion* constArray = tVar->getConstPointer();
			variable->shareConstPointer(constArray);
		}
	}

	// Constants which aren't indexable arrays get propagated by value
	// and thus don't need to initialize the symbol.
	if (variable->isConstant() && !(type.isArray() && type.getArraySize() > 1))
	{
		*intermNode = nullptr;
	}
	else
	{
		TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), line);
		*intermNode = createAssign(EOpInitialize, intermSymbol, initializer, line);
		if(*intermNode == nullptr) {
			assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
			return true;
		}
	}

	return false;
}

TPublicType TParseContext::addFullySpecifiedType(TQualifier qualifier, bool invariant, TLayoutQualifier layoutQualifier, const TPublicType &typeSpecifier)
{
	TPublicType returnType = typeSpecifier;
	returnType.qualifier = qualifier;
	returnType.invariant = invariant;
	returnType.layoutQualifier = layoutQualifier;

	if(mShaderVersion < 300)
	{
		if(typeSpecifier.array)
		{
			error(typeSpecifier.line, "not supported", "first-class array");
			returnType.clearArrayness();
		}

		if(qualifier == EvqAttribute && (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt))
		{
			error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier));
			recover();
		}

		if((qualifier == EvqVaryingIn || qualifier == EvqVaryingOut) &&
			(typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt))
		{
			error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier));
			recover();
		}
	}
	else
	{
		if(!returnType.layoutQualifier.isEmpty())
		{
			globalErrorCheck(typeSpecifier.line, symbolTable.atGlobalLevel(), "layout");
		}

		if(IsVarying(returnType.qualifier) || returnType.qualifier == EvqVertexIn || returnType.qualifier == EvqFragmentOut)
		{
			checkInputOutputTypeIsValidES3(returnType.qualifier, typeSpecifier, typeSpecifier.line);
		}
	}

	return returnType;
}

void TParseContext::checkInputOutputTypeIsValidES3(const TQualifier qualifier,
                                                   const TPublicType &type,
                                                   const TSourceLoc &qualifierLocation)
{
	// An input/output variable can never be bool or a sampler. Samplers are checked elsewhere.
	if(type.type == EbtBool)
	{
		error(qualifierLocation, "cannot be bool", getQualifierString(qualifier));
	}

	// Specific restrictions apply for vertex shader inputs and fragment shader outputs.
	switch(qualifier)
	{
	case EvqVertexIn:
		// ESSL 3.00 section 4.3.4
		if(type.array)
		{
			error(qualifierLocation, "cannot be array", getQualifierString(qualifier));
		}
		// Vertex inputs with a struct type are disallowed in singleDeclarationErrorCheck
		return;
	case EvqFragmentOut:
		// ESSL 3.00 section 4.3.6
		if(type.isMatrix())
		{
			error(qualifierLocation, "cannot be matrix", getQualifierString(qualifier));
		}
		// Fragment outputs with a struct type are disallowed in singleDeclarationErrorCheck
		return;
	default:
		break;
	}

	// Vertex shader outputs / fragment shader inputs have a different, slightly more lenient set of
	// restrictions.
	bool typeContainsIntegers = (type.type == EbtInt || type.type == EbtUInt ||
	                            type.isStructureContainingType(EbtInt) ||
	                            type.isStructureContainingType(EbtUInt));
	if(typeContainsIntegers && qualifier != EvqFlatIn && qualifier != EvqFlatOut)
	{
		error(qualifierLocation, "must use 'flat' interpolation here", getQualifierString(qualifier));
	}

	if(type.type == EbtStruct)
	{
		// ESSL 3.00 sections 4.3.4 and 4.3.6.
		// These restrictions are only implied by the ESSL 3.00 spec, but
		// the ESSL 3.10 spec lists these restrictions explicitly.
		if(type.array)
		{
			error(qualifierLocation, "cannot be an array of structures", getQualifierString(qualifier));
		}
		if(type.isStructureContainingArrays())
		{
			error(qualifierLocation, "cannot be a structure containing an array", getQualifierString(qualifier));
		}
		if(type.isStructureContainingType(EbtStruct))
		{
			error(qualifierLocation, "cannot be a structure containing a structure", getQualifierString(qualifier));
		}
		if(type.isStructureContainingType(EbtBool))
		{
			error(qualifierLocation, "cannot be a structure containing a bool", getQualifierString(qualifier));
		}
	}
}

TIntermAggregate *TParseContext::parseSingleDeclaration(TPublicType &publicType,
	const TSourceLoc &identifierOrTypeLocation,
	const TString &identifier)
{
	TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, TType(publicType), identifierOrTypeLocation);

	bool emptyDeclaration = (identifier == "");

	mDeferredSingleDeclarationErrorCheck = emptyDeclaration;

	if(emptyDeclaration)
	{
		if(publicType.isUnsizedArray())
		{
			// ESSL3 spec section 4.1.9: Array declaration which leaves the size unspecified is an error.
			// It is assumed that this applies to empty declarations as well.
			error(identifierOrTypeLocation, "empty array declaration needs to specify a size", identifier.c_str());
		}
	}
	else
	{
		if(singleDeclarationErrorCheck(publicType, identifierOrTypeLocation))
			recover();

		if(nonInitErrorCheck(identifierOrTypeLocation, identifier, publicType))
			recover();

		TVariable *variable = nullptr;
		if(!declareVariable(identifierOrTypeLocation, identifier, TType(publicType), &variable))
			recover();

		if(variable && symbol)
			symbol->setId(variable->getUniqueId());
	}

	return intermediate.makeAggregate(symbol, identifierOrTypeLocation);
}

TIntermAggregate *TParseContext::parseSingleArrayDeclaration(TPublicType &publicType,
	const TSourceLoc &identifierLocation,
	const TString &identifier,
	const TSourceLoc &indexLocation,
	TIntermTyped *indexExpression)
{
	mDeferredSingleDeclarationErrorCheck = false;

	if(singleDeclarationErrorCheck(publicType, identifierLocation))
		recover();

	if(nonInitErrorCheck(identifierLocation, identifier, publicType))
		recover();

	if(arrayTypeErrorCheck(indexLocation, publicType) || arrayQualifierErrorCheck(indexLocation, publicType))
	{
		recover();
	}

	TType arrayType(publicType);

	int size;
	if(arraySizeErrorCheck(identifierLocation, indexExpression, size))
	{
		recover();
	}
	// Make the type an array even if size check failed.
	// This ensures useless error messages regarding the variable's non-arrayness won't follow.
	arrayType.setArraySize(size);

	TVariable *variable = nullptr;
	if(!declareVariable(identifierLocation, identifier, arrayType, &variable))
		recover();

	TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
	if(variable && symbol)
		symbol->setId(variable->getUniqueId());

	return intermediate.makeAggregate(symbol, identifierLocation);
}

TIntermAggregate *TParseContext::parseSingleInitDeclaration(const TPublicType &publicType,
	const TSourceLoc &identifierLocation,
	const TString &identifier,
	const TSourceLoc &initLocation,
	TIntermTyped *initializer)
{
	mDeferredSingleDeclarationErrorCheck = false;

	if(singleDeclarationErrorCheck(publicType, identifierLocation))
		recover();

	TIntermNode *intermNode = nullptr;
	if(!executeInitializer(identifierLocation, identifier, publicType, initializer, &intermNode))
	{
		//
		// Build intermediate representation
		//
		return intermNode ? intermediate.makeAggregate(intermNode, initLocation) : nullptr;
	}
	else
	{
		recover();
		return nullptr;
	}
}

TIntermAggregate *TParseContext::parseSingleArrayInitDeclaration(TPublicType &publicType,
	const TSourceLoc &identifierLocation,
	const TString &identifier,
	const TSourceLoc &indexLocation,
	TIntermTyped *indexExpression,
	const TSourceLoc &initLocation,
	TIntermTyped *initializer)
{
	mDeferredSingleDeclarationErrorCheck = false;

	if(singleDeclarationErrorCheck(publicType, identifierLocation))
		recover();

	if(arrayTypeErrorCheck(indexLocation, publicType) || arrayQualifierErrorCheck(indexLocation, publicType))
	{
		recover();
	}

	TPublicType arrayType(publicType);

	int size = 0;
	// If indexExpression is nullptr, then the array will eventually get its size implicitly from the initializer.
	if(indexExpression != nullptr && arraySizeErrorCheck(identifierLocation, indexExpression, size))
	{
		recover();
	}
	// Make the type an array even if size check failed.
	// This ensures useless error messages regarding the variable's non-arrayness won't follow.
	arrayType.setArray(true, size);

	// initNode will correspond to the whole of "type b[n] = initializer".
	TIntermNode *initNode = nullptr;
	if(!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
	{
		return initNode ? intermediate.makeAggregate(initNode, initLocation) : nullptr;
	}
	else
	{
		recover();
		return nullptr;
	}
}

TIntermAggregate *TParseContext::parseInvariantDeclaration(const TSourceLoc &invariantLoc,
	const TSourceLoc &identifierLoc,
	const TString *identifier,
	const TSymbol *symbol)
{
	// invariant declaration
	if(globalErrorCheck(invariantLoc, symbolTable.atGlobalLevel(), "invariant varying"))
	{
		recover();
	}

	if(!symbol)
	{
		error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str());
		recover();
		return nullptr;
	}
	else
	{
		const TString kGlFrontFacing("gl_FrontFacing");
		if(*identifier == kGlFrontFacing)
		{
			error(identifierLoc, "identifier should not be declared as invariant", identifier->c_str());
			recover();
			return nullptr;
		}
		symbolTable.addInvariantVarying(std::string(identifier->c_str()));
		const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
		ASSERT(variable);
		const TType &type = variable->getType();
		TIntermSymbol *intermSymbol = intermediate.addSymbol(variable->getUniqueId(),
			*identifier, type, identifierLoc);

		TIntermAggregate *aggregate = intermediate.makeAggregate(intermSymbol, identifierLoc);
		aggregate->setOp(EOpInvariantDeclaration);
		return aggregate;
	}
}

TIntermAggregate *TParseContext::parseDeclarator(TPublicType &publicType, TIntermAggregate *aggregateDeclaration,
	const TSourceLoc &identifierLocation, const TString &identifier)
{
	// If the declaration starting this declarator list was empty (example: int,), some checks were not performed.
	if(mDeferredSingleDeclarationErrorCheck)
	{
		if(singleDeclarationErrorCheck(publicType, identifierLocation))
			recover();
		mDeferredSingleDeclarationErrorCheck = false;
	}

	if(locationDeclaratorListCheck(identifierLocation, publicType))
		recover();

	if(nonInitErrorCheck(identifierLocation, identifier, publicType))
		recover();

	TVariable *variable = nullptr;
	if(!declareVariable(identifierLocation, identifier, TType(publicType), &variable))
		recover();

	TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, TType(publicType), identifierLocation);
	if(variable && symbol)
		symbol->setId(variable->getUniqueId());

	return intermediate.growAggregate(aggregateDeclaration, symbol, identifierLocation);
}

TIntermAggregate *TParseContext::parseArrayDeclarator(TPublicType &publicType, TIntermAggregate *aggregateDeclaration,
	const TSourceLoc &identifierLocation, const TString &identifier,
	const TSourceLoc &arrayLocation, TIntermTyped *indexExpression)
{
	// If the declaration starting this declarator list was empty (example: int,), some checks were not performed.
	if(mDeferredSingleDeclarationErrorCheck)
	{
		if(singleDeclarationErrorCheck(publicType, identifierLocation))
			recover();
		mDeferredSingleDeclarationErrorCheck = false;
	}

	if(locationDeclaratorListCheck(identifierLocation, publicType))
		recover();

	if(nonInitErrorCheck(identifierLocation, identifier, publicType))
		recover();

	if(arrayTypeErrorCheck(arrayLocation, publicType) || arrayQualifierErrorCheck(arrayLocation, publicType))
	{
		recover();
	}
	else
	{
		TType arrayType = TType(publicType);
		int size;
		if(arraySizeErrorCheck(arrayLocation, indexExpression, size))
		{
			recover();
		}
		arrayType.setArraySize(size);

		TVariable *variable = nullptr;
		if(!declareVariable(identifierLocation, identifier, arrayType, &variable))
			recover();

		TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
		if(variable && symbol)
			symbol->setId(variable->getUniqueId());

		return intermediate.growAggregate(aggregateDeclaration, symbol, identifierLocation);
	}

	return nullptr;
}

TIntermAggregate *TParseContext::parseInitDeclarator(const TPublicType &publicType, TIntermAggregate *aggregateDeclaration,
	const TSourceLoc &identifierLocation, const TString &identifier,
	const TSourceLoc &initLocation, TIntermTyped *initializer)
{
	// If the declaration starting this declarator list was empty (example: int,), some checks were not performed.
	if(mDeferredSingleDeclarationErrorCheck)
	{
		if(singleDeclarationErrorCheck(publicType, identifierLocation))
			recover();
		mDeferredSingleDeclarationErrorCheck = false;
	}

	if(locationDeclaratorListCheck(identifierLocation, publicType))
		recover();

	TIntermNode *intermNode = nullptr;
	if(!executeInitializer(identifierLocation, identifier, publicType, initializer, &intermNode))
	{
		//
		// build the intermediate representation
		//
		if(intermNode)
		{
			return intermediate.growAggregate(aggregateDeclaration, intermNode, initLocation);
		}
		else
		{
			return aggregateDeclaration;
		}
	}
	else
	{
		recover();
		return nullptr;
	}
}

TIntermAggregate *TParseContext::parseArrayInitDeclarator(const TPublicType &publicType,
	TIntermAggregate *aggregateDeclaration,
	const TSourceLoc &identifierLocation,
	const TString &identifier,
	const TSourceLoc &indexLocation,
	TIntermTyped *indexExpression,
	const TSourceLoc &initLocation, TIntermTyped *initializer)
{
	// If the declaration starting this declarator list was empty (example: int,), some checks were not performed.
	if(mDeferredSingleDeclarationErrorCheck)
	{
		if(singleDeclarationErrorCheck(publicType, identifierLocation))
			recover();
		mDeferredSingleDeclarationErrorCheck = false;
	}

	if(locationDeclaratorListCheck(identifierLocation, publicType))
		recover();

	if(arrayTypeErrorCheck(indexLocation, publicType) || arrayQualifierErrorCheck(indexLocation, publicType))
	{
		recover();
	}

	TPublicType arrayType(publicType);

	int size = 0;
	// If indexExpression is nullptr, then the array will eventually get its size implicitly from the initializer.
	if(indexExpression != nullptr && arraySizeErrorCheck(identifierLocation, indexExpression, size))
	{
		recover();
	}
	// Make the type an array even if size check failed.
	// This ensures useless error messages regarding the variable's non-arrayness won't follow.
	arrayType.setArray(true, size);

	// initNode will correspond to the whole of "b[n] = initializer".
	TIntermNode *initNode = nullptr;
	if(!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
	{
		if(initNode)
		{
			return intermediate.growAggregate(aggregateDeclaration, initNode, initLocation);
		}
		else
		{
			return aggregateDeclaration;
		}
	}
	else
	{
		recover();
		return nullptr;
	}
}

void TParseContext::parseGlobalLayoutQualifier(const TPublicType &typeQualifier)
{
	if(mShaderVersion < 300)
	{
		error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 only", "layout");
		recover();
		return;
	}

	if(typeQualifier.qualifier != EvqUniform)
	{
		error(typeQualifier.line, "invalid qualifier:", getQualifierString(typeQualifier.qualifier), "global layout must be uniform");
		recover();
		return;
	}

	const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier;
	ASSERT(!layoutQualifier.isEmpty());

	if(layoutLocationErrorCheck(typeQualifier.line, typeQualifier.layoutQualifier))
	{
		recover();
		return;
	}

	if(layoutQualifier.matrixPacking != EmpUnspecified)
	{
		mDefaultMatrixPacking = layoutQualifier.matrixPacking;
	}

	if(layoutQualifier.blockStorage != EbsUnspecified)
	{
		mDefaultBlockStorage = layoutQualifier.blockStorage;
	}
}

TIntermAggregate *TParseContext::addFunctionPrototypeDeclaration(const TFunction &function, const TSourceLoc &location)
{
	// Note: symbolTableFunction could be the same as function if this is the first declaration.
	// Either way the instance in the symbol table is used to track whether the function is declared
	// multiple times.
	TFunction *symbolTableFunction =
		static_cast<TFunction *>(symbolTable.find(function.getMangledName(), getShaderVersion()));
	if(symbolTableFunction->hasPrototypeDeclaration() && mShaderVersion == 100)
	{
		// ESSL 1.00.17 section 4.2.7.
		// Doesn't apply to ESSL 3.00.4: see section 4.2.3.
		error(location, "duplicate function prototype declarations are not allowed", "function");
		recover();
	}
	symbolTableFunction->setHasPrototypeDeclaration();

	TIntermAggregate *prototype = new TIntermAggregate;
	prototype->setType(function.getReturnType());
	prototype->setName(function.getMangledName());

	for(size_t i = 0; i < function.getParamCount(); i++)
	{
		const TParameter &param = function.getParam(i);
		if(param.name != 0)
		{
			TVariable variable(param.name, *param.type);

			TIntermSymbol *paramSymbol = intermediate.addSymbol(
				variable.getUniqueId(), variable.getName(), variable.getType(), location);
			prototype = intermediate.growAggregate(prototype, paramSymbol, location);
		}
		else
		{
			TIntermSymbol *paramSymbol = intermediate.addSymbol(0, "", *param.type, location);
			prototype = intermediate.growAggregate(prototype, paramSymbol, location);
		}
	}

	prototype->setOp(EOpPrototype);

	symbolTable.pop();

	if(!symbolTable.atGlobalLevel())
	{
		// ESSL 3.00.4 section 4.2.4.
		error(location, "local function prototype declarations are not allowed", "function");
		recover();
	}

	return prototype;
}

TIntermAggregate *TParseContext::addFunctionDefinition(const TFunction &function, TIntermAggregate *functionPrototype, TIntermAggregate *functionBody, const TSourceLoc &location)
{
	//?? Check that all paths return a value if return type != void ?
	//   May be best done as post process phase on intermediate code
	if(mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue)
	{
		error(location, "function does not return a value:", "", function.getName().c_str());
		recover();
	}

	TIntermAggregate *aggregate = intermediate.growAggregate(functionPrototype, functionBody, location);
	intermediate.setAggregateOperator(aggregate, EOpFunction, location);
	aggregate->setName(function.getMangledName().c_str());
	aggregate->setType(function.getReturnType());

	// store the pragma information for debug and optimize and other vendor specific
	// information. This information can be queried from the parse tree
	aggregate->setOptimize(pragma().optimize);
	aggregate->setDebug(pragma().debug);

	if(functionBody && functionBody->getAsAggregate())
		aggregate->setEndLine(functionBody->getAsAggregate()->getEndLine());

	symbolTable.pop();
	return aggregate;
}

void TParseContext::parseFunctionPrototype(const TSourceLoc &location, TFunction *function, TIntermAggregate **aggregateOut)
{
	const TSymbol *builtIn = symbolTable.findBuiltIn(function->getMangledName(), getShaderVersion());

	if(builtIn)
	{
		error(location, "built-in functions cannot be redefined", function->getName().c_str());
		recover();
	}

	TFunction *prevDec = static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
	//
	// Note:  'prevDec' could be 'function' if this is the first time we've seen function
	// as it would have just been put in the symbol table.  Otherwise, we're looking up
	// an earlier occurance.
	//
	if(prevDec->isDefined())
	{
		// Then this function already has a body.
		error(location, "function already has a body", function->getName().c_str());
		recover();
	}
	prevDec->setDefined();
	//
	// Overload the unique ID of the definition to be the same unique ID as the declaration.
	// Eventually we will probably want to have only a single definition and just swap the
	// arguments to be the definition's arguments.
	//
	function->setUniqueId(prevDec->getUniqueId());

	// Raise error message if main function takes any parameters or return anything other than void
	if(function->getName() == "main")
	{
		if(function->getParamCount() > 0)
		{
			error(location, "function cannot take any parameter(s)", function->getName().c_str());
			recover();
		}
		if(function->getReturnType().getBasicType() != EbtVoid)
		{
			error(location, "", function->getReturnType().getBasicString(), "main function cannot return a value");
			recover();
		}
	}

	//
	// Remember the return type for later checking for RETURN statements.
	//
	mCurrentFunctionType = &(prevDec->getReturnType());
	mFunctionReturnsValue = false;

	//
	// Insert parameters into the symbol table.
	// If the parameter has no name, it's not an error, just don't insert it
	// (could be used for unused args).
	//
	// Also, accumulate the list of parameters into the HIL, so lower level code
	// knows where to find parameters.
	//
	TIntermAggregate *paramNodes = new TIntermAggregate;
	for(size_t i = 0; i < function->getParamCount(); i++)
	{
		const TParameter &param = function->getParam(i);
		if(param.name != 0)
		{
			TVariable *variable = new TVariable(param.name, *param.type);
			//
			// Insert the parameters with name in the symbol table.
			//
			if(!symbolTable.declare(variable))
			{
				error(location, "redefinition", variable->getName().c_str());
				recover();
				paramNodes = intermediate.growAggregate(
					paramNodes, intermediate.addSymbol(0, "", *param.type, location), location);
				continue;
			}

			//
			// Add the parameter to the HIL
			//
			TIntermSymbol *symbol = intermediate.addSymbol(
				variable->getUniqueId(), variable->getName(), variable->getType(), location);

			paramNodes = intermediate.growAggregate(paramNodes, symbol, location);
		}
		else
		{
			paramNodes = intermediate.growAggregate(
				paramNodes, intermediate.addSymbol(0, "", *param.type, location), location);
		}
	}
	intermediate.setAggregateOperator(paramNodes, EOpParameters, location);
	*aggregateOut = paramNodes;
	setLoopNestingLevel(0);
}

TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TFunction *function)
{
	//
	// We don't know at this point whether this is a function definition or a prototype.
	// The definition production code will check for redefinitions.
	// In the case of ESSL 1.00 the prototype production code will also check for redeclarations.
	//
	// Return types and parameter qualifiers must match in all redeclarations, so those are checked
	// here.
	//
	TFunction *prevDec = static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
	if(getShaderVersion() >= 300 && symbolTable.hasUnmangledBuiltIn(function->getName().c_str()))
	{
		// With ESSL 3.00, names of built-in functions cannot be redeclared as functions.
		// Therefore overloading or redefining builtin functions is an error.
		error(location, "Name of a built-in function cannot be redeclared as function", function->getName().c_str());
	}
	else if(prevDec)
	{
		if(prevDec->getReturnType() != function->getReturnType())
		{
			error(location, "overloaded functions must have the same return type",
				function->getReturnType().getBasicString());
			recover();
		}
		for(size_t i = 0; i < prevDec->getParamCount(); ++i)
		{
			if(prevDec->getParam(i).type->getQualifier() != function->getParam(i).type->getQualifier())
			{
				error(location, "overloaded functions must have the same parameter qualifiers",
					function->getParam(i).type->getQualifierString());
				recover();
			}
		}
	}

	//
	// Check for previously declared variables using the same name.
	//
	TSymbol *prevSym = symbolTable.find(function->getName(), getShaderVersion());
	if(prevSym)
	{
		if(!prevSym->isFunction())
		{
			error(location, "redefinition", function->getName().c_str(), "function");
			recover();
		}
	}
	else
	{
		// Insert the unmangled name to detect potential future redefinition as a variable.
		TFunction *unmangledFunction = new TFunction(NewPoolTString(function->getName().c_str()), function->getReturnType());
		symbolTable.getOuterLevel()->insertUnmangled(unmangledFunction);
	}

	// We're at the inner scope level of the function's arguments and body statement.
	// Add the function prototype to the surrounding scope instead.
	symbolTable.getOuterLevel()->insert(function);

	//
	// If this is a redeclaration, it could also be a definition, in which case, we want to use the
	// variable names from this one, and not the one that's
	// being redeclared.  So, pass back up this declaration, not the one in the symbol table.
	//
	return function;
}

TFunction *TParseContext::addConstructorFunc(const TPublicType &publicTypeIn)
{
	TPublicType publicType = publicTypeIn;
	TOperator op = EOpNull;
	if(publicType.userDef)
	{
		op = EOpConstructStruct;
	}
	else
	{
		op = TypeToConstructorOperator(TType(publicType));
		if(op == EOpNull)
		{
			error(publicType.line, "cannot construct this type", getBasicString(publicType.type));
			recover();
			publicType.type = EbtFloat;
			op = EOpConstructFloat;
		}
	}

	TString tempString;
	TType type(publicType);
	return new TFunction(&tempString, type, op);
}

// This function is used to test for the correctness of the parameters passed to various constructor functions
// and also convert them to the right datatype if it is allowed and required.
//
// Returns 0 for an error or the constructed node (aggregate or typed) for no error.
//
TIntermTyped* TParseContext::addConstructor(TIntermNode* arguments, const TType* type, TOperator op, TFunction* fnCall, const TSourceLoc &line)
{
	TIntermAggregate *aggregateArguments = arguments->getAsAggregate();

	if(!aggregateArguments)
	{
		aggregateArguments = new TIntermAggregate;
		aggregateArguments->getSequence().push_back(arguments);
	}

	if(type->isArray())
	{
		// GLSL ES 3.00 section 5.4.4: Each argument must be the same type as the element type of
		// the array.
		for(TIntermNode *&argNode : aggregateArguments->getSequence())
		{
			const TType &argType = argNode->getAsTyped()->getType();
			// It has already been checked that the argument is not an array.
			ASSERT(!argType.isArray());
			if(!argType.sameElementType(*type))
			{
				error(line, "Array constructor argument has an incorrect type", "Error");
				return nullptr;
			}
		}
	}
	else if(op == EOpConstructStruct)
	{
		const TFieldList &fields = type->getStruct()->fields();
		TIntermSequence &args = aggregateArguments->getSequence();

		for(size_t i = 0; i < fields.size(); i++)
		{
			if(args[i]->getAsTyped()->getType() != *fields[i]->type())
			{
				error(line, "Structure constructor arguments do not match structure fields", "Error");
				recover();

				return nullptr;
			}
		}
	}

	// Turn the argument list itself into a constructor
	TIntermAggregate *constructor = intermediate.setAggregateOperator(aggregateArguments, op, line);
	TIntermTyped *constConstructor = foldConstConstructor(constructor, *type);
	if(constConstructor)
	{
		return constConstructor;
	}

	return constructor;
}

TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, const TType& type)
{
	aggrNode->setType(type);
	if (aggrNode->isConstantFoldable()) {
		bool returnVal = false;
		ConstantUnion* unionArray = new ConstantUnion[type.getObjectSize()];
		if (aggrNode->getSequence().size() == 1)  {
			returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), type, true);
		}
		else {
			returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), type);
		}
		if (returnVal)
			return nullptr;

		return intermediate.addConstantUnion(unionArray, type, aggrNode->getLine());
	}

	return nullptr;
}

//
// This function returns the tree representation for the vector field(s) being accessed from contant vector.
// If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is
// returned, else an aggregate node is returned (for v.xy). The input to this function could either be the symbol
// node or it could be the intermediate tree representation of accessing fields in a constant structure or column of
// a constant matrix.
//
TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, const TSourceLoc &line)
{
	TIntermTyped* typedNode;
	TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();

	ConstantUnion *unionArray;
	if (tempConstantNode) {
		unionArray = tempConstantNode->getUnionArrayPointer();

		if (!unionArray) {
			return node;
		}
	} else { // The node has to be either a symbol node or an aggregate node or a tempConstant node, else, its an error
		error(line, "Cannot offset into the vector", "Error");
		recover();

		return nullptr;
	}

	ConstantUnion* constArray = new ConstantUnion[fields.num];

	int objSize = static_cast<int>(node->getType().getObjectSize());
	for (int i = 0; i < fields.num; i++) {
		if (fields.offsets[i] >= objSize) {
			std::stringstream extraInfoStream;
			extraInfoStream << "vector field selection out of range '" << fields.offsets[i] << "'";
			std::string extraInfo = extraInfoStream.str();
			error(line, "", "[", extraInfo.c_str());
			recover();
			fields.offsets[i] = 0;
		}

		constArray[i] = unionArray[fields.offsets[i]];

	}

	TType type(node->getType().getBasicType(), node->getType().getPrecision(), EvqConstExpr, fields.num);
	typedNode = intermediate.addConstantUnion(constArray, type, line);
	return typedNode;
}

//
// This function returns the column being accessed from a constant matrix. The values are retrieved from
// the symbol table and parse-tree is built for a vector (each column of a matrix is a vector). The input
// to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a
// constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure)
//
TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, const TSourceLoc &line)
{
	TIntermTyped* typedNode;
	TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();

	if (index >= node->getType().getNominalSize()) {
		std::stringstream extraInfoStream;
		extraInfoStream << "matrix field selection out of range '" << index << "'";
		std::string extraInfo = extraInfoStream.str();
		error(line, "", "[", extraInfo.c_str());
		recover();
		index = 0;
	}

	if (tempConstantNode) {
		 ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
		 int size = tempConstantNode->getType().getNominalSize();
		 typedNode = intermediate.addConstantUnion(&unionArray[size*index], tempConstantNode->getType(), line);
	} else {
		error(line, "Cannot offset into the matrix", "Error");
		recover();

		return nullptr;
	}

	return typedNode;
}


//
// This function returns an element of an array accessed from a constant array. The values are retrieved from
// the symbol table and parse-tree is built for the type of the element. The input
// to the function could either be a symbol node (a[0] where a is a constant array)that represents a
// constant array or it could be the tree representation of the constant array (s.a1[0] where s is a constant structure)
//
TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc &line)
{
	TIntermTyped* typedNode;
	TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
	TType arrayElementType = node->getType();
	arrayElementType.clearArrayness();

	if (index >= node->getType().getArraySize()) {
		std::stringstream extraInfoStream;
		extraInfoStream << "array field selection out of range '" << index << "'";
		std::string extraInfo = extraInfoStream.str();
		error(line, "", "[", extraInfo.c_str());
		recover();
		index = 0;
	}

	size_t arrayElementSize = arrayElementType.getObjectSize();

	if (tempConstantNode) {
		 ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
		 typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line);
	} else {
		error(line, "Cannot offset into the array", "Error");
		recover();

		return nullptr;
	}

	return typedNode;
}


//
// This function returns the value of a particular field inside a constant structure from the symbol table.
// If there is an embedded/nested struct, it appropriately calls addConstStructNested or addConstStructFromAggr
// function and returns the parse-tree with the values of the embedded/nested struct.
//
TIntermTyped* TParseContext::addConstStruct(const TString& identifier, TIntermTyped* node, const TSourceLoc &line)
{
	const TFieldList &fields = node->getType().getStruct()->fields();
	TIntermTyped *typedNode;
	size_t instanceSize = 0;
	TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion();

	for(const auto &field : fields) {
		if (field->name() == identifier) {
			break;
		} else {
			instanceSize += field->type()->getObjectSize();
		}
	}

	if (tempConstantNode) {
		 ConstantUnion* constArray = tempConstantNode->getUnionArrayPointer();

		 typedNode = intermediate.addConstantUnion(constArray+instanceSize, tempConstantNode->getType(), line); // type will be changed in the calling function
	} else {
		error(line, "Cannot offset into the structure", "Error");
		recover();

		return nullptr;
	}

	return typedNode;
}

//
// Interface/uniform blocks
//
TIntermAggregate* TParseContext::addInterfaceBlock(const TPublicType& typeQualifier, const TSourceLoc& nameLine, const TString& blockName, TFieldList* fieldList,
												   const TString* instanceName, const TSourceLoc& instanceLine, TIntermTyped* arrayIndex, const TSourceLoc& arrayIndexLine)
{
	if(reservedErrorCheck(nameLine, blockName))
		recover();

	if(typeQualifier.qualifier != EvqUniform)
	{
		error(typeQualifier.line, "invalid qualifier:", getQualifierString(typeQualifier.qualifier), "interface blocks must be uniform");
		recover();
	}

	TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier;
	if(layoutLocationErrorCheck(typeQualifier.line, blockLayoutQualifier))
	{
		recover();
	}

	if(blockLayoutQualifier.matrixPacking == EmpUnspecified)
	{
		blockLayoutQualifier.matrixPacking = mDefaultMatrixPacking;
	}

	if(blockLayoutQualifier.blockStorage == EbsUnspecified)
	{
		blockLayoutQualifier.blockStorage = mDefaultBlockStorage;
	}

	TSymbol* blockNameSymbol = new TSymbol(&blockName);
	if(!symbolTable.declare(blockNameSymbol)) {
		error(nameLine, "redefinition", blockName.c_str(), "interface block name");
		recover();
	}

	// check for sampler types and apply layout qualifiers
	for(const auto &field : *fieldList) {
		TType* fieldType = field->type();
		if(IsSampler(fieldType->getBasicType())) {
			error(field->line(), "unsupported type", fieldType->getBasicString(), "sampler types are not allowed in interface blocks");
			recover();
		}

		const TQualifier qualifier = fieldType->getQualifier();
		switch(qualifier)
		{
		case EvqGlobal:
		case EvqUniform:
			break;
		default:
			error(field->line(), "invalid qualifier on interface block member", getQualifierString(qualifier));
			recover();
			break;
		}

		// check layout qualifiers
		TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier();
		if(layoutLocationErrorCheck(field->line(), fieldLayoutQualifier))
		{
			recover();
		}

		if(fieldLayoutQualifier.blockStorage != EbsUnspecified)
		{
			error(field->line(), "invalid layout qualifier:", getBlockStorageString(fieldLayoutQualifier.blockStorage), "cannot be used here");
			recover();
		}

		if(fieldLayoutQualifier.matrixPacking == EmpUnspecified)
		{
			fieldLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking;
		}
		else if(!fieldType->isMatrix() && (fieldType->getBasicType() != EbtStruct))
		{
			warning(field->line(), "extraneous layout qualifier:", getMatrixPackingString(fieldLayoutQualifier.matrixPacking), "only has an effect on matrix types");
		}

		fieldType->setLayoutQualifier(fieldLayoutQualifier);

		// Recursively propagate the matrix packing setting down to all block/structure members
		fieldType->setMatrixPackingIfUnspecified(fieldLayoutQualifier.matrixPacking);
	}

	// add array index
	int arraySize = 0;
	if(arrayIndex)
	{
		if(arraySizeErrorCheck(arrayIndexLine, arrayIndex, arraySize))
			recover();
	}

	TInterfaceBlock* interfaceBlock = new TInterfaceBlock(&blockName, fieldList, instanceName, arraySize, blockLayoutQualifier);
	TType interfaceBlockType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier, arraySize);

	TString symbolName = "";
	int symbolId = 0;

	if(!instanceName)
	{
		// define symbols for the members of the interface block
		for(const auto &field : *fieldList)
		{
			TType* fieldType = field->type();

			// set parent pointer of the field variable
			fieldType->setInterfaceBlock(interfaceBlock);

			TVariable* fieldVariable = new TVariable(&field->name(), *fieldType);
			fieldVariable->setQualifier(typeQualifier.qualifier);

			if(!symbolTable.declare(fieldVariable)) {
				error(field->line(), "redefinition", field->name().c_str(), "interface block member name");
				recover();
			}
		}
	}
	else
	{
		if(reservedErrorCheck(nameLine, *instanceName))
			recover();

		// add a symbol for this interface block
		TVariable* instanceTypeDef = new TVariable(instanceName, interfaceBlockType, false);
		instanceTypeDef->setQualifier(typeQualifier.qualifier);

		if(!symbolTable.declare(instanceTypeDef)) {
			error(instanceLine, "redefinition", instanceName->c_str(), "interface block instance name");
			recover();
		}

		symbolId = instanceTypeDef->getUniqueId();
		symbolName = instanceTypeDef->getName();
	}

	TIntermAggregate *aggregate = intermediate.makeAggregate(intermediate.addSymbol(symbolId, symbolName, interfaceBlockType, typeQualifier.line), nameLine);
	aggregate->setOp(EOpDeclaration);

	exitStructDeclaration();
	return aggregate;
}

//
// Parse an array index expression
//
TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc &location, TIntermTyped *indexExpression)
{
	TIntermTyped *indexedExpression = nullptr;

	if(!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
	{
		if(baseExpression->getAsSymbolNode())
		{
			error(location, " left of '[' is not of type array, matrix, or vector ",
				baseExpression->getAsSymbolNode()->getSymbol().c_str());
		}
		else
		{
			error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
		}
		recover();
	}

	TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();

	if(indexExpression->getQualifier() == EvqConstExpr && indexConstantUnion)   // TODO: Qualifier check redundant?
	{
		int index = indexConstantUnion->getIConst(0);
		if(index < 0)
		{
			std::stringstream infoStream;
			infoStream << index;
			std::string info = infoStream.str();
			error(location, "negative index", info.c_str());
			recover();
			index = 0;
		}
		if(baseExpression->getType().getQualifier() == EvqConstExpr && baseExpression->getAsConstantUnion())   // TODO: Qualifier check redundant?
		{
			if(baseExpression->isArray())
			{
				// constant folding for arrays
				indexedExpression = addConstArrayNode(index, baseExpression, location);
			}
			else if(baseExpression->isVector())
			{
				// constant folding for vectors
				TVectorFields fields;
				fields.num = 1;
				fields.offsets[0] = index; // need to do it this way because v.xy sends fields integer array
				indexedExpression = addConstVectorNode(fields, baseExpression, location);
			}
			else if(baseExpression->isMatrix())
			{
				// constant folding for matrices
				indexedExpression = addConstMatrixNode(index, baseExpression, location);
			}
		}
		else
		{
			int safeIndex = -1;

			if(baseExpression->isArray())
			{
				if(index >= baseExpression->getType().getArraySize())
				{
					std::stringstream extraInfoStream;
					extraInfoStream << "array index out of range '" << index << "'";
					std::string extraInfo = extraInfoStream.str();
					error(location, "", "[", extraInfo.c_str());
					recover();
					safeIndex = baseExpression->getType().getArraySize() - 1;
				}
			}
			else if((baseExpression->isVector() || baseExpression->isMatrix()) &&
				baseExpression->getType().getNominalSize() <= index)
			{
				std::stringstream extraInfoStream;
				extraInfoStream << "field selection out of range '" << index << "'";
				std::string extraInfo = extraInfoStream.str();
				error(location, "", "[", extraInfo.c_str());
				recover();
				safeIndex = baseExpression->getType().getNominalSize() - 1;
			}

			// Don't modify the data of the previous constant union, because it can point
			// to builtins, like gl_MaxDrawBuffers. Instead use a new sanitized object.
			if(safeIndex != -1)
			{
				ConstantUnion *safeConstantUnion = new ConstantUnion();
				safeConstantUnion->setIConst(safeIndex);
				indexConstantUnion->replaceConstantUnion(safeConstantUnion);
			}

			indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location);
		}
	}
	else
	{
		if(baseExpression->isInterfaceBlock())
		{
			error(location, "",
				"[", "array indexes for interface blocks arrays must be constant integral expressions");
			recover();
		}
		else if(baseExpression->getQualifier() == EvqFragmentOut)
		{
			error(location, "", "[", "array indexes for fragment outputs must be constant integral expressions");
			recover();
		}

		indexedExpression = intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location);
	}

	if(indexedExpression == 0)
	{
		ConstantUnion *unionArray = new ConstantUnion[1];
		unionArray->setFConst(0.0f);
		indexedExpression = intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConstExpr), location);
	}
	else if(baseExpression->isArray())
	{
		const TType &baseType = baseExpression->getType();
		if(baseType.getStruct())
		{
			TType copyOfType(baseType.getStruct());
			indexedExpression->setType(copyOfType);
		}
		else if(baseType.isInterfaceBlock())
		{
			TType copyOfType(baseType.getInterfaceBlock(), EvqTemporary, baseType.getLayoutQualifier(), 0);
			indexedExpression->setType(copyOfType);
		}
		else
		{
			indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(),
				EvqTemporary, static_cast<unsigned char>(baseExpression->getNominalSize()),
				static_cast<unsigned char>(baseExpression->getSecondarySize())));
		}

		if(baseExpression->getType().getQualifier() == EvqConstExpr)
		{
			indexedExpression->getTypePointer()->setQualifier(EvqConstExpr);
		}
	}
	else if(baseExpression->isMatrix())
	{
		TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConstExpr ? EvqConstExpr : EvqTemporary;
		indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(),
			qualifier, static_cast<unsigned char>(baseExpression->getSecondarySize())));
	}
	else if(baseExpression->isVector())
	{
		TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConstExpr ? EvqConstExpr : EvqTemporary;
		indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier));
	}
	else
	{
		indexedExpression->setType(baseExpression->getType());
	}

	return indexedExpression;
}

TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression, const TSourceLoc &dotLocation,
	const TString &fieldString, const TSourceLoc &fieldLocation)
{
	TIntermTyped *indexedExpression = nullptr;

	if(baseExpression->isArray())
	{
		error(fieldLocation, "cannot apply dot operator to an array", ".");
		recover();
	}

	if(baseExpression->isVector())
	{
		TVectorFields fields;
		if(!parseVectorFields(fieldString, baseExpression->getNominalSize(), fields, fieldLocation))
		{
			fields.num = 1;
			fields.offsets[0] = 0;
			recover();
		}

		if(baseExpression->getAsConstantUnion())
		{
			// constant folding for vector fields
			indexedExpression = addConstVectorNode(fields, baseExpression, fieldLocation);
			if(indexedExpression == 0)
			{
				recover();
				indexedExpression = baseExpression;
			}
		}
		else
		{
			TString vectorString = fieldString;
			TIntermTyped *index = intermediate.addSwizzle(fields, fieldLocation);
			indexedExpression = intermediate.addIndex(EOpVectorSwizzle, baseExpression, index, dotLocation);
			indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(),
				baseExpression->getQualifier() == EvqConstExpr ? EvqConstExpr : EvqTemporary, (unsigned char)vectorString.size()));
		}
	}
	else if(baseExpression->getBasicType() == EbtStruct)
	{
		bool fieldFound = false;
		const TFieldList &fields = baseExpression->getType().getStruct()->fields();
		if(fields.empty())
		{
			error(dotLocation, "structure has no fields", "Internal Error");
			recover();
			indexedExpression = baseExpression;
		}
		else
		{
			unsigned int i;
			for(i = 0; i < fields.size(); ++i)
			{
				if(fields[i]->name() == fieldString)
				{
					fieldFound = true;
					break;
				}
			}
			if(fieldFound)
			{
				if(baseExpression->getType().getQualifier() == EvqConstExpr)
				{
					indexedExpression = addConstStruct(fieldString, baseExpression, dotLocation);
					if(indexedExpression == 0)
					{
						recover();
						indexedExpression = baseExpression;
					}
					else
					{
						indexedExpression->setType(*fields[i]->type());
						// change the qualifier of the return type, not of the structure field
						// as the structure definition is shared between various structures.
						indexedExpression->getTypePointer()->setQualifier(EvqConstExpr);
					}
				}
				else
				{
					TIntermTyped *index = TIntermTyped::CreateIndexNode(i);
					index->setLine(fieldLocation);
					indexedExpression = intermediate.addIndex(EOpIndexDirectStruct, baseExpression, index, dotLocation);
					indexedExpression->setType(*fields[i]->type());
				}
			}
			else
			{
				error(dotLocation, " no such field in structure", fieldString.c_str());
				recover();
				indexedExpression = baseExpression;
			}
		}
	}
	else if(baseExpression->isInterfaceBlock())
	{
		bool fieldFound = false;
		const TFieldList &fields = baseExpression->getType().getInterfaceBlock()->fields();
		if(fields.empty())
		{
			error(dotLocation, "interface block has no fields", "Internal Error");
			recover();
			indexedExpression = baseExpression;
		}
		else
		{
			unsigned int i;
			for(i = 0; i < fields.size(); ++i)
			{
				if(fields[i]->name() == fieldString)
				{
					fieldFound = true;
					break;
				}
			}
			if(fieldFound)
			{
				ConstantUnion *unionArray = new ConstantUnion[1];
				unionArray->setIConst(i);
				TIntermTyped *index = intermediate.addConstantUnion(unionArray, *fields[i]->type(), fieldLocation);
				indexedExpression = intermediate.addIndex(EOpIndexDirectInterfaceBlock, baseExpression, index,
					dotLocation);
				indexedExpression->setType(*fields[i]->type());
			}
			else
			{
				error(dotLocation, " no such field in interface block", fieldString.c_str());
				recover();
				indexedExpression = baseExpression;
			}
		}
	}
	else
	{
		if(mShaderVersion < 300)
		{
			error(dotLocation, " field selection requires structure or vector on left hand side",
				fieldString.c_str());
		}
		else
		{
			error(dotLocation,
				" field selection requires structure, vector, or interface block on left hand side",
				fieldString.c_str());
		}
		recover();
		indexedExpression = baseExpression;
	}

	return indexedExpression;
}

TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine)
{
	TLayoutQualifier qualifier;

	qualifier.location = -1;
	qualifier.matrixPacking = EmpUnspecified;
	qualifier.blockStorage = EbsUnspecified;

	if(qualifierType == "shared")
	{
		qualifier.blockStorage = EbsShared;
	}
	else if(qualifierType == "packed")
	{
		qualifier.blockStorage = EbsPacked;
	}
	else if(qualifierType == "std140")
	{
		qualifier.blockStorage = EbsStd140;
	}
	else if(qualifierType == "row_major")
	{
		qualifier.matrixPacking = EmpRowMajor;
	}
	else if(qualifierType == "column_major")
	{
		qualifier.matrixPacking = EmpColumnMajor;
	}
	else if(qualifierType == "location")
	{
		error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str(), "location requires an argument");
		recover();
	}
	else
	{
		error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
		recover();
	}

	return qualifier;
}

TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine, const TString &intValueString, int intValue, const TSourceLoc& intValueLine)
{
	TLayoutQualifier qualifier;

	qualifier.location = -1;  // -1 isn't a valid location, it means the value isn't set. Negative values are checked lower in this function.
	qualifier.matrixPacking = EmpUnspecified;
	qualifier.blockStorage = EbsUnspecified;

	if (qualifierType != "location")
	{
		error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str(), "only location may have arguments");
		recover();
	}
	else
	{
		// must check that location is non-negative
		if (intValue < 0)
		{
			error(intValueLine, "out of range:", intValueString.c_str(), "location must be non-negative");
			recover();
		}
		else
		{
			qualifier.location = intValue;
		}
	}

	return qualifier;
}

TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier, TLayoutQualifier rightQualifier)
{
	TLayoutQualifier joinedQualifier = leftQualifier;

	if (rightQualifier.location != -1)
	{
		joinedQualifier.location = rightQualifier.location;
	}
	if(rightQualifier.matrixPacking != EmpUnspecified)
	{
		joinedQualifier.matrixPacking = rightQualifier.matrixPacking;
	}
	if(rightQualifier.blockStorage != EbsUnspecified)
	{
		joinedQualifier.blockStorage = rightQualifier.blockStorage;
	}

	return joinedQualifier;
}


TPublicType TParseContext::joinInterpolationQualifiers(const TSourceLoc &interpolationLoc, TQualifier interpolationQualifier,
	const TSourceLoc &storageLoc, TQualifier storageQualifier)
{
	TQualifier mergedQualifier = EvqSmoothIn;

	if(storageQualifier == EvqFragmentIn) {
		if(interpolationQualifier == EvqSmooth)
			mergedQualifier = EvqSmoothIn;
		else if(interpolationQualifier == EvqFlat)
			mergedQualifier = EvqFlatIn;
		else UNREACHABLE(interpolationQualifier);
	}
	else if(storageQualifier == EvqCentroidIn) {
		if(interpolationQualifier == EvqSmooth)
			mergedQualifier = EvqCentroidIn;
		else if(interpolationQualifier == EvqFlat)
			mergedQualifier = EvqFlatIn;
		else UNREACHABLE(interpolationQualifier);
	}
	else if(storageQualifier == EvqVertexOut) {
		if(interpolationQualifier == EvqSmooth)
			mergedQualifier = EvqSmoothOut;
		else if(interpolationQualifier == EvqFlat)
			mergedQualifier = EvqFlatOut;
		else UNREACHABLE(interpolationQualifier);
	}
	else if(storageQualifier == EvqCentroidOut) {
		if(interpolationQualifier == EvqSmooth)
			mergedQualifier = EvqCentroidOut;
		else if(interpolationQualifier == EvqFlat)
			mergedQualifier = EvqFlatOut;
		else UNREACHABLE(interpolationQualifier);
	}
	else {
		error(interpolationLoc, "interpolation qualifier requires a fragment 'in' or vertex 'out' storage qualifier", getQualifierString(interpolationQualifier));
		recover();

		mergedQualifier = storageQualifier;
	}

	TPublicType type;
	type.setBasic(EbtVoid, mergedQualifier, storageLoc);
	return type;
}

TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier, TFieldList *fieldList)
{
	if(voidErrorCheck(typeSpecifier.line, (*fieldList)[0]->name(), typeSpecifier.type))
	{
		recover();
	}

	for(const auto &field : *fieldList)
	{
		//
		// Careful not to replace already known aspects of type, like array-ness
		//
		TType *type = field->type();
		type->setBasicType(typeSpecifier.type);
		type->setNominalSize(typeSpecifier.primarySize);
		type->setSecondarySize(typeSpecifier.secondarySize);
		type->setPrecision(typeSpecifier.precision);
		type->setQualifier(typeSpecifier.qualifier);
		type->setLayoutQualifier(typeSpecifier.layoutQualifier);

		// don't allow arrays of arrays
		if(type->isArray())
		{
			if(arrayTypeErrorCheck(typeSpecifier.line, typeSpecifier))
				recover();
		}
		if(typeSpecifier.array)
			type->setArraySize(typeSpecifier.arraySize);
		if(typeSpecifier.userDef)
		{
			type->setStruct(typeSpecifier.userDef->getStruct());
		}

		if(structNestingErrorCheck(typeSpecifier.line, *field))
		{
			recover();
		}
	}

	return fieldList;
}

TPublicType TParseContext::addStructure(const TSourceLoc &structLine, const TSourceLoc &nameLine,
	const TString *structName, TFieldList *fieldList)
{
	TStructure *structure = new TStructure(structName, fieldList);
	TType *structureType = new TType(structure);

	// Store a bool in the struct if we're at global scope, to allow us to
	// skip the local struct scoping workaround in HLSL.
	structure->setUniqueId(TSymbolTableLevel::nextUniqueId());
	structure->setAtGlobalScope(symbolTable.atGlobalLevel());

	if(!structName->empty())
	{
		if(reservedErrorCheck(nameLine, *structName))
		{
			recover();
		}
		TVariable *userTypeDef = new TVariable(structName, *structureType, true);
		if(!symbolTable.declare(userTypeDef))
		{
			error(nameLine, "redefinition", structName->c_str(), "struct");
			recover();
		}
	}

	// ensure we do not specify any storage qualifiers on the struct members
	for(const auto &field : *fieldList)
	{
		const TQualifier qualifier = field->type()->getQualifier();
		switch(qualifier)
		{
		case EvqGlobal:
		case EvqTemporary:
			break;
		default:
			error(field->line(), "invalid qualifier on struct member", getQualifierString(qualifier));
			recover();
			break;
		}
	}

	TPublicType publicType;
	publicType.setBasic(EbtStruct, EvqTemporary, structLine);
	publicType.userDef = structureType;
	exitStructDeclaration();

	return publicType;
}

bool TParseContext::enterStructDeclaration(const TSourceLoc &line, const TString& identifier)
{
	++mStructNestingLevel;

	// Embedded structure definitions are not supported per GLSL ES spec.
	// They aren't allowed in GLSL either, but we need to detect this here
	// so we don't rely on the GLSL compiler to catch it.
	if (mStructNestingLevel > 1) {
		error(line, "", "Embedded struct definitions are not allowed");
		return true;
	}

	return false;
}

void TParseContext::exitStructDeclaration()
{
	--mStructNestingLevel;
}

bool TParseContext::structNestingErrorCheck(const TSourceLoc &line, const TField &field)
{
	static const int kWebGLMaxStructNesting = 4;

	if(field.type()->getBasicType() != EbtStruct)
	{
		return false;
	}

	// We're already inside a structure definition at this point, so add
	// one to the field's struct nesting.
	if(1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting)
	{
		std::stringstream reasonStream;
		reasonStream << "Reference of struct type "
			<< field.type()->getStruct()->name().c_str()
			<< " exceeds maximum allowed nesting level of "
			<< kWebGLMaxStructNesting;
		std::string reason = reasonStream.str();
		error(line, reason.c_str(), field.name().c_str(), "");
		return true;
	}

	return false;
}

TIntermTyped *TParseContext::createUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc, const TType *funcReturnType)
{
	if(child == nullptr)
	{
		return nullptr;
	}

	switch(op)
	{
	case EOpLogicalNot:
		if(child->getBasicType() != EbtBool ||
			child->isMatrix() ||
			child->isArray() ||
			child->isVector())
		{
			return nullptr;
		}
		break;
	case EOpBitwiseNot:
		if((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) ||
			child->isMatrix() ||
			child->isArray())
		{
			return nullptr;
		}
		break;
	case EOpPostIncrement:
	case EOpPreIncrement:
	case EOpPostDecrement:
	case EOpPreDecrement:
	case EOpNegative:
		if(child->getBasicType() == EbtStruct ||
			child->getBasicType() == EbtBool ||
			child->isArray())
		{
			return nullptr;
		}
		// Operators for built-ins are already type checked against their prototype.
	default:
		break;
	}

	return intermediate.addUnaryMath(op, child, loc, funcReturnType);
}

TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
{
	TIntermTyped *node = createUnaryMath(op, child, loc, nullptr);
	if(node == nullptr)
	{
		unaryOpError(loc, getOperatorString(op), child->getCompleteString());
		recover();
		return child;
	}
	return node;
}

TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
{
	if(lValueErrorCheck(loc, getOperatorString(op), child))
		recover();
	return addUnaryMath(op, child, loc);
}

bool TParseContext::binaryOpCommonCheck(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc)
{
	if(left->isArray() || right->isArray())
	{
		if(mShaderVersion < 300)
		{
			error(loc, "Invalid operation for arrays", getOperatorString(op));
			return false;
		}

		if(left->isArray() != right->isArray())
		{
			error(loc, "array / non-array mismatch", getOperatorString(op));
			return false;
		}

		switch(op)
		{
		case EOpEqual:
		case EOpNotEqual:
		case EOpAssign:
		case EOpInitialize:
			break;
		default:
			error(loc, "Invalid operation for arrays", getOperatorString(op));
			return false;
		}
		// At this point, size of implicitly sized arrays should be resolved.
		if(left->getArraySize() != right->getArraySize())
		{
			error(loc, "array size mismatch", getOperatorString(op));
			return false;
		}
	}

	// Check ops which require integer / ivec parameters
	bool isBitShift = false;
	switch(op)
	{
	case EOpBitShiftLeft:
	case EOpBitShiftRight:
	case EOpBitShiftLeftAssign:
	case EOpBitShiftRightAssign:
		// Unsigned can be bit-shifted by signed and vice versa, but we need to
		// check that the basic type is an integer type.
		isBitShift = true;
		if(!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType()))
		{
			return false;
		}
		break;
	case EOpBitwiseAnd:
	case EOpBitwiseXor:
	case EOpBitwiseOr:
	case EOpBitwiseAndAssign:
	case EOpBitwiseXorAssign:
	case EOpBitwiseOrAssign:
		// It is enough to check the type of only one operand, since later it
		// is checked that the operand types match.
		if(!IsInteger(left->getBasicType()))
		{
			return false;
		}
		break;
	default:
		break;
	}

	// GLSL ES 1.00 and 3.00 do not support implicit type casting.
	// So the basic type should usually match.
	if(!isBitShift && left->getBasicType() != right->getBasicType())
	{
		return false;
	}

	// Check that type sizes match exactly on ops that require that.
	// Also check restrictions for structs that contain arrays or samplers.
	switch(op)
	{
	case EOpAssign:
	case EOpInitialize:
	case EOpEqual:
	case EOpNotEqual:
		// ESSL 1.00 sections 5.7, 5.8, 5.9
		if(mShaderVersion < 300 && left->getType().isStructureContainingArrays())
		{
			error(loc, "undefined operation for structs containing arrays", getOperatorString(op));
			return false;
		}
		// Samplers as l-values are disallowed also in ESSL 3.00, see section 4.1.7,
		// we interpret the spec so that this extends to structs containing samplers,
		// similarly to ESSL 1.00 spec.
		if((mShaderVersion < 300 || op == EOpAssign || op == EOpInitialize) &&
			left->getType().isStructureContainingSamplers())
		{
			error(loc, "undefined operation for structs containing samplers", getOperatorString(op));
			return false;
		}
	case EOpLessThan:
	case EOpGreaterThan:
	case EOpLessThanEqual:
	case EOpGreaterThanEqual:
		if((left->getNominalSize() != right->getNominalSize()) ||
			(left->getSecondarySize() != right->getSecondarySize()))
		{
			return false;
		}
		break;
	case EOpAdd:
	case EOpSub:
	case EOpDiv:
	case EOpIMod:
	case EOpBitShiftLeft:
	case EOpBitShiftRight:
	case EOpBitwiseAnd:
	case EOpBitwiseXor:
	case EOpBitwiseOr:
	case EOpAddAssign:
	case EOpSubAssign:
	case EOpDivAssign:
	case EOpIModAssign:
	case EOpBitShiftLeftAssign:
	case EOpBitShiftRightAssign:
	case EOpBitwiseAndAssign:
	case EOpBitwiseXorAssign:
	case EOpBitwiseOrAssign:
		if((left->isMatrix() && right->isVector()) || (left->isVector() && right->isMatrix()))
		{
			return false;
		}

		// Are the sizes compatible?
		if(left->getNominalSize() != right->getNominalSize() || left->getSecondarySize() != right->getSecondarySize())
		{
			// If the nominal sizes of operands do not match:
			// One of them must be a scalar.
			if(!left->isScalar() && !right->isScalar())
				return false;

			// In the case of compound assignment other than multiply-assign,
			// the right side needs to be a scalar. Otherwise a vector/matrix
			// would be assigned to a scalar. A scalar can't be shifted by a
			// vector either.
			if(!right->isScalar() && (IsAssignment(op) || op == EOpBitShiftLeft || op == EOpBitShiftRight))
				return false;
		}
		break;
	default:
		break;
	}

	return true;
}

TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &loc)
{
	TBasicType switchType = init->getBasicType();
	if((switchType != EbtInt && switchType != EbtUInt) ||
	   init->isMatrix() ||
	   init->isArray() ||
	   init->isVector())
	{
		error(init->getLine(), "init-expression in a switch statement must be a scalar integer", "switch");
		recover();
		return nullptr;
	}

	if(statementList)
	{
		if(!ValidateSwitch::validate(switchType, this, statementList, loc))
		{
			recover();
			return nullptr;
		}
	}

	TIntermSwitch *node = intermediate.addSwitch(init, statementList, loc);
	if(node == nullptr)
	{
		error(loc, "erroneous switch statement", "switch");
		recover();
		return nullptr;
	}
	return node;
}

TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc)
{
	if(mSwitchNestingLevel == 0)
	{
		error(loc, "case labels need to be inside switch statements", "case");
		recover();
		return nullptr;
	}
	if(condition == nullptr)
	{
		error(loc, "case label must have a condition", "case");
		recover();
		return nullptr;
	}
	if((condition->getBasicType() != EbtInt && condition->getBasicType() != EbtUInt) ||
	   condition->isMatrix() ||
	   condition->isArray() ||
	   condition->isVector())
	{
		error(condition->getLine(), "case label must be a scalar integer", "case");
		recover();
	}
	TIntermConstantUnion *conditionConst = condition->getAsConstantUnion();
	if(conditionConst == nullptr)
	{
		error(condition->getLine(), "case label must be constant", "case");
		recover();
	}
	TIntermCase *node = intermediate.addCase(condition, loc);
	if(node == nullptr)
	{
		error(loc, "erroneous case statement", "case");
		recover();
		return nullptr;
	}
	return node;
}

TIntermCase *TParseContext::addDefault(const TSourceLoc &loc)
{
	if(mSwitchNestingLevel == 0)
	{
		error(loc, "default labels need to be inside switch statements", "default");
		recover();
		return nullptr;
	}
	TIntermCase *node = intermediate.addCase(nullptr, loc);
	if(node == nullptr)
	{
		error(loc, "erroneous default statement", "default");
		recover();
		return nullptr;
	}
	return node;
}
TIntermTyped *TParseContext::createAssign(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc)
{
	if(binaryOpCommonCheck(op, left, right, loc))
	{
		return intermediate.addAssign(op, left, right, loc);
	}
	return nullptr;
}

TIntermTyped *TParseContext::addAssign(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc)
{
	TIntermTyped *node = createAssign(op, left, right, loc);
	if(node == nullptr)
	{
		assignError(loc, "assign", left->getCompleteString(), right->getCompleteString());
		recover();
		return left;
	}
	return node;
}

TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op, TIntermTyped *left, TIntermTyped *right,
	const TSourceLoc &loc)
{
	if(!binaryOpCommonCheck(op, left, right, loc))
		return nullptr;

	switch(op)
	{
	case EOpEqual:
	case EOpNotEqual:
		break;
	case EOpLessThan:
	case EOpGreaterThan:
	case EOpLessThanEqual:
	case EOpGreaterThanEqual:
		ASSERT(!left->isArray() && !right->isArray());
		if(left->isMatrix() || left->isVector() ||
			left->getBasicType() == EbtStruct)
		{
			return nullptr;
		}
		break;
	case EOpLogicalOr:
	case EOpLogicalXor:
	case EOpLogicalAnd:
		ASSERT(!left->isArray() && !right->isArray());
		if(left->getBasicType() != EbtBool ||
			left->isMatrix() || left->isVector())
		{
			return nullptr;
		}
		break;
	case EOpAdd:
	case EOpSub:
	case EOpDiv:
	case EOpMul:
		ASSERT(!left->isArray() && !right->isArray());
		if(left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool)
		{
			return nullptr;
		}
		break;
	case EOpIMod:
		ASSERT(!left->isArray() && !right->isArray());
		// Note that this is only for the % operator, not for mod()
		if(left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat)
		{
			return nullptr;
		}
		break;
		// Note that for bitwise ops, type checking is done in promote() to
		// share code between ops and compound assignment
	default:
		break;
	}

	return intermediate.addBinaryMath(op, left, right, loc);
}

TIntermTyped *TParseContext::addBinaryMath(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc)
{
	TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
	if(node == 0)
	{
		binaryOpError(loc, getOperatorString(op), left->getCompleteString(), right->getCompleteString());
		recover();
		return left;
	}
	return node;
}

TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc)
{
	TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
	if(node == 0)
	{
		binaryOpError(loc, getOperatorString(op), left->getCompleteString(), right->getCompleteString());
		recover();
		ConstantUnion *unionArray = new ConstantUnion[1];
		unionArray->setBConst(false);
		return intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConstExpr), loc);
	}
	return node;
}

TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc)
{
	switch(op)
	{
	case EOpContinue:
		if(mLoopNestingLevel <= 0)
		{
			error(loc, "continue statement only allowed in loops", "");
			recover();
		}
		break;
	case EOpBreak:
		if(mLoopNestingLevel <= 0 && mSwitchNestingLevel <= 0)
		{
			error(loc, "break statement only allowed in loops and switch statements", "");
			recover();
		}
		break;
	case EOpReturn:
		if(mCurrentFunctionType->getBasicType() != EbtVoid)
		{
			error(loc, "non-void function must return a value", "return");
			recover();
		}
		break;
	default:
		// No checks for discard
		break;
	}
	return intermediate.addBranch(op, loc);
}

TIntermBranch *TParseContext::addBranch(TOperator op, TIntermTyped *returnValue, const TSourceLoc &loc)
{
	ASSERT(op == EOpReturn);
	mFunctionReturnsValue = true;
	if(mCurrentFunctionType->getBasicType() == EbtVoid)
	{
		error(loc, "void function cannot return a value", "return");
		recover();
	}
	else if(*mCurrentFunctionType != returnValue->getType())
	{
		error(loc, "function return is not matching type:", "return");
		recover();
	}
	return intermediate.addBranch(op, returnValue, loc);
}

TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall, TIntermNode *paramNode, TIntermNode *thisNode, const TSourceLoc &loc, bool *fatalError)
{
	*fatalError = false;
	TOperator op = fnCall->getBuiltInOp();
	TIntermTyped *callNode = nullptr;

	if(thisNode != nullptr)
	{
		ConstantUnion *unionArray = new ConstantUnion[1];
		int arraySize = 0;
		TIntermTyped *typedThis = thisNode->getAsTyped();
		if(fnCall->getName() != "length")
		{
			error(loc, "invalid method", fnCall->getName().c_str());
			recover();
		}
		else if(paramNode != nullptr)
		{
			error(loc, "method takes no parameters", "length");
			recover();
		}
		else if(typedThis == nullptr || !typedThis->isArray())
		{
			error(loc, "length can only be called on arrays", "length");
			recover();
		}
		else
		{
			arraySize = typedThis->getArraySize();
		}
		unionArray->setIConst(arraySize);
		callNode = intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConstExpr), loc);
	}
	else if(op != EOpNull)
	{
		//
		// Then this should be a constructor.
		// Don't go through the symbol table for constructors.
		// Their parameters will be verified algorithmically.
		//
		TType type(EbtVoid, EbpUndefined);  // use this to get the type back
		if(!constructorErrorCheck(loc, paramNode, *fnCall, op, &type))
		{
			//
			// It's a constructor, of type 'type'.
			//
			callNode = addConstructor(paramNode, &type, op, fnCall, loc);
		}

		if(callNode == nullptr)
		{
			recover();
			callNode = intermediate.setAggregateOperator(nullptr, op, loc);
		}
	}
	else
	{
		//
		// Not a constructor.  Find it in the symbol table.
		//
		const TFunction *fnCandidate;
		bool builtIn;
		fnCandidate = findFunction(loc, fnCall, &builtIn);
		if(fnCandidate)
		{
			//
			// A declared function.
			//
			if(builtIn && !fnCandidate->getExtension().empty() &&
				extensionErrorCheck(loc, fnCandidate->getExtension()))
			{
				recover();
			}
			op = fnCandidate->getBuiltInOp();
			if(builtIn && op != EOpNull)
			{
				//
				// A function call mapped to a built-in operation.
				//
				if(fnCandidate->getParamCount() == 1)
				{
					//
					// Treat it like a built-in unary operator.
					//
					callNode = createUnaryMath(op, paramNode->getAsTyped(), loc, &fnCandidate->getReturnType());
					if(callNode == nullptr)
					{
						std::stringstream extraInfoStream;
						extraInfoStream << "built in unary operator function.  Type: "
							<< static_cast<TIntermTyped*>(paramNode)->getCompleteString();
						std::string extraInfo = extraInfoStream.str();
						error(paramNode->getLine(), " wrong operand type", "Internal Error", extraInfo.c_str());
						*fatalError = true;
						return nullptr;
					}
				}
				else
				{
					TIntermAggregate *aggregate = intermediate.setAggregateOperator(paramNode, op, loc);
					aggregate->setType(fnCandidate->getReturnType());

					// Some built-in functions have out parameters too.
					functionCallLValueErrorCheck(fnCandidate, aggregate);

					callNode = aggregate;

					if(fnCandidate->getParamCount() == 2)
					{
						TIntermSequence &parameters = paramNode->getAsAggregate()->getSequence();
						TIntermTyped *left = parameters[0]->getAsTyped();
						TIntermTyped *right = parameters[1]->getAsTyped();

						TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
						TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
						if (leftTempConstant && rightTempConstant)
						{
							TIntermTyped *typedReturnNode = leftTempConstant->fold(op, rightTempConstant, infoSink());

							if(typedReturnNode)
							{
								callNode = typedReturnNode;
							}
						}
					}
				}
			}
			else
			{
				// This is a real function call

				TIntermAggregate *aggregate = intermediate.setAggregateOperator(paramNode, EOpFunctionCall, loc);
				aggregate->setType(fnCandidate->getReturnType());

				// this is how we know whether the given function is a builtIn function or a user defined function
				// if builtIn == false, it's a userDefined -> could be an overloaded builtIn function also
				// if builtIn == true, it's definitely a builtIn function with EOpNull
				if(!builtIn)
					aggregate->setUserDefined();
				aggregate->setName(fnCandidate->getMangledName());

				callNode = aggregate;

				functionCallLValueErrorCheck(fnCandidate, aggregate);
			}
		}
		else
		{
			// error message was put out by findFunction()
			// Put on a dummy node for error recovery
			ConstantUnion *unionArray = new ConstantUnion[1];
			unionArray->setFConst(0.0f);
			callNode = intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConstExpr), loc);
			recover();
		}
	}
	delete fnCall;
	return callNode;
}

TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock, const TSourceLoc &loc)
{
	if(boolErrorCheck(loc, cond))
		recover();

	if(trueBlock->getType() != falseBlock->getType())
	{
		binaryOpError(loc, ":", trueBlock->getCompleteString(), falseBlock->getCompleteString());
		recover();
		return falseBlock;
	}
	// ESSL1 sections 5.2 and 5.7:
	// ESSL3 section 5.7:
	// Ternary operator is not among the operators allowed for structures/arrays.
	if(trueBlock->isArray() || trueBlock->getBasicType() == EbtStruct)
	{
		error(loc, "ternary operator is not allowed for structures or arrays", ":");
		recover();
		return falseBlock;
	}
	return intermediate.addSelection(cond, trueBlock, falseBlock, loc);
}

//
// Parse an array of strings using yyparse.
//
// Returns 0 for success.
//
int PaParseStrings(int count, const char* const string[], const int length[],
				   TParseContext* context) {
	if ((count == 0) || !string)
		return 1;

	if (glslang_initialize(context))
		return 1;

	int error = glslang_scan(count, string, length, context);
	if (!error)
		error = glslang_parse(context);

	glslang_finalize(context);

	return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
}



