/*-------------------------------------------------------------------------
 * drawElements Quality Program Random Shader Generator
 * ----------------------------------------------------
 *
 * Copyright 2014 The Android Open Source Project
 *
 * 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.
 *
 *//*!
 * \file
 * \brief Expressions.
 *//*--------------------------------------------------------------------*/

#include "rsgExpression.hpp"
#include "rsgVariableManager.hpp"
#include "rsgBinaryOps.hpp"
#include "rsgBuiltinFunctions.hpp"
#include "rsgUtils.hpp"
#include "deMath.h"

using std::vector;

namespace rsg
{

namespace
{

class IsReadableEntry
{
public:
	typedef ValueEntryIterator<IsReadableEntry> Iterator;

	IsReadableEntry (deUint32 exprFlags)
		: m_exprFlags(exprFlags)
	{
	}

	bool operator() (const ValueEntry* entry) const
	{
		if ((m_exprFlags & CONST_EXPR) && (entry->getVariable()->getStorage() != Variable::STORAGE_CONST))
			return false;

		return true;
	}

private:
	deUint32 m_exprFlags;
};

class IsReadableIntersectingEntry : public IsReadableEntry
{
public:
	typedef ValueEntryIterator<IsReadableIntersectingEntry> Iterator;

	IsReadableIntersectingEntry (ConstValueRangeAccess valueRange, deUint32 exprFlags)
		: IsReadableEntry	(exprFlags)
		, m_valueRange		(valueRange)
	{
	}

	bool operator() (const ValueEntry* entry) const
	{
		if (!IsReadableEntry::operator()(entry))
			return false;

		if (entry->getValueRange().getType() != m_valueRange.getType())
			return false;

		if (!entry->getValueRange().intersects(m_valueRange))
			return false;

		return true;
	}

private:
	ConstValueRangeAccess m_valueRange;
};

class IsWritableIntersectingEntry : public IsWritableEntry
{
public:
	typedef ValueEntryIterator<IsWritableIntersectingEntry> Iterator;

	IsWritableIntersectingEntry (ConstValueRangeAccess valueRange)
		: m_valueRange(valueRange)
	{
	}

	bool operator() (const ValueEntry* entry) const
	{
		return IsWritableEntry::operator()(entry) &&
			   entry->getVariable()->getType() == m_valueRange.getType() &&
			   entry->getValueRange().intersects(m_valueRange);
	}

private:
	ConstValueRangeAccess m_valueRange;
};

class IsWritableSupersetEntry : public IsWritableEntry
{
public:
	typedef ValueEntryIterator<IsWritableSupersetEntry> Iterator;

	IsWritableSupersetEntry (ConstValueRangeAccess valueRange)
		: m_valueRange(valueRange)
	{
	}

	bool operator() (const ValueEntry* entry) const
	{
		return IsWritableEntry()(entry) &&
			   entry->getVariable()->getType() == m_valueRange.getType() &&
			   entry->getValueRange().isSupersetOf(m_valueRange);
	}

private:
	ConstValueRangeAccess m_valueRange;
};

class IsSamplerEntry
{
public:
	typedef ValueEntryIterator<IsSamplerEntry> Iterator;

	IsSamplerEntry (VariableType::Type type)
		: m_type(type)
	{
		DE_ASSERT(m_type == VariableType::TYPE_SAMPLER_2D || m_type == VariableType::TYPE_SAMPLER_CUBE);
	}

	bool operator() (const ValueEntry* entry) const
	{
		if (entry->getVariable()->getType() == VariableType(m_type, 1))
		{
			DE_ASSERT(entry->getVariable()->getStorage() == Variable::STORAGE_UNIFORM);
			return true;
		}
		else
			return false;
	}

private:
	VariableType::Type m_type;
};

inline bool getWeightedBool (de::Random& random, float trueWeight)
{
	DE_ASSERT(de::inRange<float>(trueWeight, 0.0f, 1.0f));
	return (random.getFloat() < trueWeight);
}

void computeRandomValueRangeForInfElements (GeneratorState& state, ValueRangeAccess valueRange)
{
	const VariableType&	type	= valueRange.getType();
	de::Random&		rnd		= state.getRandom();

	switch (type.getBaseType())
	{
		case VariableType::TYPE_BOOL:
			// No need to handle bool as it will be false, true
			break;

		case VariableType::TYPE_INT:
			for (int ndx = 0; ndx < type.getNumElements(); ndx++)
			{
				if (valueRange.getMin().component(ndx).asScalar() != Scalar::min<int>() ||
					valueRange.getMax().component(ndx).asScalar() != Scalar::max<int>())
					continue;

				const int minIntVal		= -16;
				const int maxIntVal		=  16;
				const int maxRangeLen	= maxIntVal - minIntVal;

				int rangeLen	= rnd.getInt(0, maxRangeLen);
				int minVal		= minIntVal + rnd.getInt(0, maxRangeLen-rangeLen);
				int maxVal		= minVal + rangeLen;

				valueRange.getMin().component(ndx).asInt() = minVal;
				valueRange.getMax().component(ndx).asInt() = maxVal;
			}
			break;

		case VariableType::TYPE_FLOAT:
			for (int ndx = 0; ndx < type.getNumElements(); ndx++)
			{
				if (valueRange.getMin().component(ndx).asScalar() != Scalar::min<float>() ||
					valueRange.getMax().component(ndx).asScalar() != Scalar::max<float>())
					continue;

				const float step			= 0.1f;
				const int	maxSteps		= 320;
				const float minFloatVal		= -16.0f;

				int rangeLen	= rnd.getInt(0, maxSteps);
				int minStep		= rnd.getInt(0, maxSteps-rangeLen);

				float minVal	= minFloatVal + step*minStep;
				float maxVal	= minVal + step*rangeLen;

				valueRange.getMin().component(ndx).asFloat() = minVal;
				valueRange.getMax().component(ndx).asFloat() = maxVal;
			}
			break;

		default:
			DE_ASSERT(DE_FALSE);
			throw Exception("computeRandomValueRangeForInfElements(): unsupported type");
	}
}

void setInfiniteRange (ValueRangeAccess valueRange)
{
	const VariableType& type = valueRange.getType();

	switch (type.getBaseType())
	{
		case VariableType::TYPE_BOOL:
			for (int ndx = 0; ndx < type.getNumElements(); ndx++)
			{
				valueRange.getMin().component(ndx) = Scalar::min<bool>();
				valueRange.getMax().component(ndx) = Scalar::max<bool>();
			}
			break;

		case VariableType::TYPE_INT:
			for (int ndx = 0; ndx < type.getNumElements(); ndx++)
			{
				valueRange.getMin().component(ndx) = Scalar::min<int>();
				valueRange.getMax().component(ndx) = Scalar::max<int>();
			}
			break;

		case VariableType::TYPE_FLOAT:
			for (int ndx = 0; ndx < type.getNumElements(); ndx++)
			{
				valueRange.getMin().component(ndx) = Scalar::min<float>();
				valueRange.getMax().component(ndx) = Scalar::max<float>();
			}
			break;

		default:
			DE_ASSERT(DE_FALSE);
			throw Exception("setInfiniteRange(): unsupported type");
	}
}

bool canAllocateVariable (const GeneratorState& state, const VariableType& type)
{
	DE_ASSERT(!type.isVoid());

	if (state.getExpressionFlags() & NO_VAR_ALLOCATION)
		return false;

	if (state.getVariableManager().getNumAllocatedScalars() + type.getScalarSize() > state.getShaderParameters().maxCombinedVariableScalars)
		return false;

	return true;
}

template <class T> float		getWeight	(const GeneratorState& state, ConstValueRangeAccess valueRange)	{ return T::getWeight(state, valueRange);	}
template <class T> Expression*	create		(GeneratorState& state, ConstValueRangeAccess valueRange)		{ return new T(state, valueRange);			}

struct ExpressionSpec
{
	float			(*getWeight)		(const GeneratorState& state, ConstValueRangeAccess valueRange);
	Expression*		(*create)			(GeneratorState& state, ConstValueRangeAccess valueRange);
};

static const ExpressionSpec s_expressionSpecs[] =
{
	{ getWeight<FloatLiteral>,		create<FloatLiteral>		},
	{ getWeight<IntLiteral>,		create<IntLiteral>			},
	{ getWeight<BoolLiteral>,		create<BoolLiteral>			},
	{ getWeight<ConstructorOp>,		create<ConstructorOp>		},
	{ getWeight<AssignOp>,			create<AssignOp>			},
	{ getWeight<VariableRead>,		create<VariableRead>		},
	{ getWeight<MulOp>,				create<MulOp>				},
	{ getWeight<AddOp>,				create<AddOp>				},
	{ getWeight<SubOp>,				create<SubOp>				},
	{ getWeight<LessThanOp>,		create<LessThanOp>			},
	{ getWeight<LessOrEqualOp>,		create<LessOrEqualOp>		},
	{ getWeight<GreaterThanOp>,		create<GreaterThanOp>		},
	{ getWeight<GreaterOrEqualOp>,	create<GreaterOrEqualOp>	},
	{ getWeight<EqualOp>,			create<EqualOp>				},
	{ getWeight<NotEqualOp>,		create<NotEqualOp>			},
	{ getWeight<SwizzleOp>,			create<SwizzleOp>			},
	{ getWeight<SinOp>,				create<SinOp>				},
	{ getWeight<CosOp>,				create<CosOp>				},
	{ getWeight<TanOp>,				create<TanOp>				},
	{ getWeight<AsinOp>,			create<AsinOp>				},
	{ getWeight<AcosOp>,			create<AcosOp>				},
	{ getWeight<AtanOp>,			create<AtanOp>				},
	{ getWeight<ExpOp>,				create<ExpOp>				},
	{ getWeight<LogOp>,				create<LogOp>				},
	{ getWeight<Exp2Op>,			create<Exp2Op>				},
	{ getWeight<Log2Op>,			create<Log2Op>				},
	{ getWeight<SqrtOp>,			create<SqrtOp>				},
	{ getWeight<InvSqrtOp>,			create<InvSqrtOp>			},
	{ getWeight<ParenOp>,			create<ParenOp>				},
	{ getWeight<TexLookup>,			create<TexLookup>			}
};

static const ExpressionSpec s_lvalueSpecs[] =
{
	{ getWeight<VariableWrite>,		create<VariableWrite>	}
};

#if !defined(DE_MAX)
#	define DE_MAX(a, b) ((b) > (a) ? (b) : (a))
#endif

enum
{
	MAX_EXPRESSION_SPECS = (int)DE_MAX(DE_LENGTH_OF_ARRAY(s_expressionSpecs), DE_LENGTH_OF_ARRAY(s_lvalueSpecs))
};

const ExpressionSpec* chooseExpression (GeneratorState& state, const ExpressionSpec* specs, int numSpecs, ConstValueRangeAccess valueRange)
{
	float weights[MAX_EXPRESSION_SPECS];

	DE_ASSERT(numSpecs <= (int)DE_LENGTH_OF_ARRAY(weights));

	// Compute weights
	for (int ndx = 0; ndx < numSpecs; ndx++)
		weights[ndx] = specs[ndx].getWeight(state, valueRange);

	// Choose
	return &state.getRandom().chooseWeighted<const ExpressionSpec&>(specs, specs+numSpecs, weights);
}

} // anonymous

Expression::~Expression (void)
{
}

Expression* Expression::createRandom (GeneratorState& state, ConstValueRangeAccess valueRange)
{
	return chooseExpression(state, s_expressionSpecs, (int)DE_LENGTH_OF_ARRAY(s_expressionSpecs), valueRange)->create(state, valueRange);
}

Expression* Expression::createRandomLValue (GeneratorState& state, ConstValueRangeAccess valueRange)
{
	return chooseExpression(state, s_lvalueSpecs, (int)DE_LENGTH_OF_ARRAY(s_lvalueSpecs), valueRange)->create(state, valueRange);
}

FloatLiteral::FloatLiteral (GeneratorState& state, ConstValueRangeAccess valueRange)
	: m_value(VariableType::getScalarType(VariableType::TYPE_FLOAT))
{
	float minVal	= -10.0f;
	float maxVal	= +10.0f;
	float step		= 0.25f;

	if (valueRange.getType() == VariableType(VariableType::TYPE_FLOAT, 1))
	{
		minVal = valueRange.getMin().component(0).asFloat();
		maxVal = valueRange.getMax().component(0).asFloat();

		if (Scalar::min<float>() == minVal)
			minVal = -10.0f;

		if (Scalar::max<float>() == maxVal)
			maxVal = +10.0f;
	}

	int numSteps = (int)((maxVal-minVal)/step) + 1;

	float			value	= deFloatClamp(minVal + step*state.getRandom().getInt(0, numSteps), minVal, maxVal);
	ExecValueAccess	access	= m_value.getValue(VariableType::getScalarType(VariableType::TYPE_FLOAT));

	for (int ndx = 0; ndx < EXEC_VEC_WIDTH; ndx++)
		access.asFloat(ndx) = value;
}

float FloatLiteral::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
{
	DE_UNREF(state);
	const VariableType& type = valueRange.getType();
	if (type == VariableType(VariableType::TYPE_FLOAT, 1))
	{
		float minVal = valueRange.getMin().asFloat();
		float maxVal = valueRange.getMax().asFloat();

		if (Scalar::min<float>() == minVal && Scalar::max<float>() == maxVal)
			return 0.1f;

		// Weight based on value range length
		float rangeLength = maxVal - minVal;

		DE_ASSERT(rangeLength >= 0.0f);
		return deFloatMax(0.1f, 1.0f - rangeLength);
	}
	else if (type.isVoid())
		return unusedValueWeight;
	else
		return 0.0f;
}

void FloatLiteral::tokenize (GeneratorState& state, TokenStream& str) const
{
	DE_UNREF(state);
	str << Token(m_value.getValue(VariableType::getScalarType(VariableType::TYPE_FLOAT)).asFloat(0));
}

IntLiteral::IntLiteral (GeneratorState& state, ConstValueRangeAccess valueRange)
	: m_value(VariableType::getScalarType(VariableType::TYPE_INT))
{
	int minVal = -16;
	int maxVal = +16;

	if (valueRange.getType() == VariableType(VariableType::TYPE_INT, 1))
	{
		minVal = valueRange.getMin().component(0).asInt();
		maxVal = valueRange.getMax().component(0).asInt();

		if (Scalar::min<int>() == minVal)
			minVal = -16;

		if (Scalar::max<int>() == maxVal)
			maxVal = 16;
	}

	int				value	= state.getRandom().getInt(minVal, maxVal);
	ExecValueAccess	access	= m_value.getValue(VariableType::getScalarType(VariableType::TYPE_INT));

	for (int ndx = 0; ndx < EXEC_VEC_WIDTH; ndx++)
		access.asInt(ndx) = value;
}

float IntLiteral::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
{
	DE_UNREF(state);
	const VariableType& type = valueRange.getType();
	if (type == VariableType(VariableType::TYPE_INT, 1))
	{
		int minVal = valueRange.getMin().asInt();
		int maxVal = valueRange.getMax().asInt();

		if (Scalar::min<int>() == minVal && Scalar::max<int>() == maxVal)
			return 0.1f;

		int rangeLength = maxVal - minVal;

		DE_ASSERT(rangeLength >= 0);
		return deFloatMax(0.1f, 1.0f - rangeLength/4.0f);
	}
	else if (type.isVoid())
		return unusedValueWeight;
	else
		return 0.0f;
}

void IntLiteral::tokenize (GeneratorState& state, TokenStream& str) const
{
	DE_UNREF(state);
	str << Token(m_value.getValue(VariableType::getScalarType(VariableType::TYPE_INT)).asInt(0));
}

BoolLiteral::BoolLiteral (GeneratorState& state, ConstValueRangeAccess valueRange)
	: m_value(VariableType::getScalarType(VariableType::TYPE_BOOL))
{
	int minVal = 0;
	int maxVal = 1;

	if (valueRange.getType() == VariableType(VariableType::TYPE_BOOL, 1))
	{
		minVal = valueRange.getMin().component(0).asBool() ? 1 : 0;
		maxVal = valueRange.getMax().component(0).asBool() ? 1 : 0;
	}

	bool			value	= state.getRandom().getInt(minVal, maxVal) == 1;
	ExecValueAccess	access	= m_value.getValue(VariableType::getScalarType(VariableType::TYPE_BOOL));

	for (int ndx = 0; ndx < EXEC_VEC_WIDTH; ndx++)
		access.asBool(ndx) = value;
}

float BoolLiteral::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
{
	DE_UNREF(state);
	const VariableType& type = valueRange.getType();
	if (type == VariableType(VariableType::TYPE_BOOL, 1))
		return 0.5f;
	else if (type.isVoid())
		return unusedValueWeight;
	else
		return 0.0f;
}

void BoolLiteral::tokenize (GeneratorState& state, TokenStream& str) const
{
	DE_UNREF(state);
	str << Token(m_value.getValue(VariableType::getScalarType(VariableType::TYPE_BOOL)).asBool(0));
}

namespace
{

// \note int-bool and float-bool conversions handled in a special way.
template <typename SrcType, typename DstType>
inline DstType convert (SrcType src)
{
	if (Scalar::min<SrcType>() == src)
		return Scalar::min<DstType>().template as<DstType>();
	else if (Scalar::max<SrcType>() == src)
		return Scalar::max<DstType>().template as<DstType>();
	else
		return DstType(src);
}

// According to GLSL ES spec.
template <> inline bool		convert<float, bool>	(float src)	{ return src != 0.0f;					}
template <> inline bool		convert<int, bool>		(int src)	{ return src != 0;						}
template <> inline float	convert<bool, float>	(bool src)	{ return src ? 1.0f : 0.0f;				}
template <> inline int		convert<bool, int>		(bool src)	{ return src ? 1 : 0;					}

template <> inline int convert<float, int> (float src)
{
	if (Scalar::min<float>() == src)
		return Scalar::min<int>().as<int>();
	else if (Scalar::max<float>() == src)
		return Scalar::max<int>().as<int>();
	else if (src > 0.0f)
		return (int)deFloatFloor(src);
	else
		return (int)deFloatCeil(src);
}

template <typename SrcType, typename DstType>
inline void convertValueRange (SrcType srcMin, SrcType srcMax, DstType& dstMin, DstType& dstMax)
{
	dstMin = convert<SrcType, DstType>(srcMin);
	dstMax = convert<SrcType, DstType>(srcMax);
}

template <>
inline void convertValueRange<float, int> (float srcMin, float srcMax, int& dstMin, int& dstMax)
{
	if (Scalar::min<float>() == srcMin)
		dstMin = Scalar::min<int>().as<int>();
	else
		dstMin = (int)deFloatCeil(srcMin);

	if (Scalar::max<float>() == srcMax)
		dstMax = Scalar::max<int>().as<int>();
	else
		dstMax = (int)deFloatFloor(srcMax);
}

template <>
inline void convertValueRange<float, bool> (float srcMin, float srcMax, bool& dstMin, bool& dstMax)
{
	dstMin = srcMin > 0.0f;
	dstMax = srcMax > 0.0f;
}

// \todo [pyry] More special cases?

// Returns whether it is possible to convert some SrcType value range to given DstType valueRange
template <typename SrcType, typename DstType>
bool isConversionOk (DstType min, DstType max)
{
	SrcType sMin, sMax;
	convertValueRange(min, max, sMin, sMax);
	return sMin <= sMax &&
		   de::inRange(convert<SrcType, DstType>(sMin), min, max) &&
		   de::inRange(convert<SrcType, DstType>(sMax), min, max);
}

// Work-around for non-deterministic float behavior
template <> bool isConversionOk<float, float> (float, float) { return true; }

// \todo [2011-03-26 pyry] Provide this in ValueAccess?
template <typename T>	T				getValueAccessValue			(ConstValueAccess access);
template<>				inline float	getValueAccessValue<float>	(ConstValueAccess access) { return access.asFloat();	}
template<>				inline int		getValueAccessValue<int>	(ConstValueAccess access) { return access.asInt();		}
template<>				inline bool		getValueAccessValue<bool>	(ConstValueAccess access) { return access.asBool();		}

template <typename T>	T&				getValueAccessValue			(ValueAccess access);
template<>				inline float&	getValueAccessValue<float>	(ValueAccess access) { return access.asFloat();		}
template<>				inline int&		getValueAccessValue<int>	(ValueAccess access) { return access.asInt();		}
template<>				inline bool&	getValueAccessValue<bool>	(ValueAccess access) { return access.asBool();		}

template <typename SrcType, typename DstType>
bool isConversionOk (ConstValueRangeAccess valueRange)
{
	return isConversionOk<SrcType>(getValueAccessValue<DstType>(valueRange.getMin()), getValueAccessValue<DstType>(valueRange.getMax()));
}

template <typename SrcType, typename DstType>
void convertValueRangeTempl (ConstValueRangeAccess src, ValueRangeAccess dst)
{
	DstType dMin, dMax;
	convertValueRange(getValueAccessValue<SrcType>(src.getMin()), getValueAccessValue<SrcType>(src.getMax()), dMin, dMax);
	getValueAccessValue<DstType>(dst.getMin()) = dMin;
	getValueAccessValue<DstType>(dst.getMax()) = dMax;
}

template <typename SrcType, typename DstType>
void convertExecValueTempl (ExecConstValueAccess src, ExecValueAccess dst)
{
	for (int ndx = 0; ndx < EXEC_VEC_WIDTH; ndx++)
		dst.as<DstType>(ndx) = convert<SrcType, DstType>(src.as<SrcType>(ndx));
}

typedef bool (*IsConversionOkFunc)		(ConstValueRangeAccess);
typedef void (*ConvertValueRangeFunc)	(ConstValueRangeAccess, ValueRangeAccess);
typedef void (*ConvertExecValueFunc)	(ExecConstValueAccess, ExecValueAccess);

inline int getBaseTypeConvNdx (VariableType::Type type)
{
	switch (type)
	{
		case VariableType::TYPE_FLOAT:	return 0;
		case VariableType::TYPE_INT:	return 1;
		case VariableType::TYPE_BOOL:	return 2;
		default:						return -1;
	}
}

bool isConversionOk (VariableType::Type srcType, VariableType::Type dstType, ConstValueRangeAccess valueRange)
{
	// [src][dst]
	static const IsConversionOkFunc convTable[3][3] =
	{
		{ isConversionOk<float, float>, isConversionOk<float,	int>,	isConversionOk<float,	bool>	},
		{ isConversionOk<int,	float>,	isConversionOk<int,		int>,	isConversionOk<int,		bool>	},
		{ isConversionOk<bool,	float>,	isConversionOk<bool,	int>,	isConversionOk<bool,	bool>	}
	};
	return convTable[getBaseTypeConvNdx(srcType)][getBaseTypeConvNdx(dstType)](valueRange);
}

void convertValueRange (ConstValueRangeAccess src, ValueRangeAccess dst)
{
	// [src][dst]
	static const ConvertValueRangeFunc convTable[3][3] =
	{
		{ convertValueRangeTempl<float, float>, convertValueRangeTempl<float,	int>,	convertValueRangeTempl<float,	bool>	},
		{ convertValueRangeTempl<int,	float>,	convertValueRangeTempl<int,		int>,	convertValueRangeTempl<int,		bool>	},
		{ convertValueRangeTempl<bool,	float>,	convertValueRangeTempl<bool,	int>,	convertValueRangeTempl<bool,	bool>	}
	};

	convTable[getBaseTypeConvNdx(src.getType().getBaseType())][getBaseTypeConvNdx(dst.getType().getBaseType())](src, dst);
}

void convertExecValue (ExecConstValueAccess src, ExecValueAccess dst)
{
	// [src][dst]
	static const ConvertExecValueFunc convTable[3][3] =
	{
		{ convertExecValueTempl<float,	float>,	convertExecValueTempl<float,	int>,	convertExecValueTempl<float,	bool>	},
		{ convertExecValueTempl<int,	float>,	convertExecValueTempl<int,		int>,	convertExecValueTempl<int,		bool>	},
		{ convertExecValueTempl<bool,	float>,	convertExecValueTempl<bool,		int>,	convertExecValueTempl<bool,		bool>	}
	};

	convTable[getBaseTypeConvNdx(src.getType().getBaseType())][getBaseTypeConvNdx(dst.getType().getBaseType())](src, dst);
}

} // anonymous

ConstructorOp::ConstructorOp (GeneratorState& state, ConstValueRangeAccess valueRange)
	: m_valueRange(valueRange)
{
	if (valueRange.getType().isVoid())
	{
		// Use random range
		const int maxScalars = 4; // We don't have to be able to assign this value to anywhere
		m_valueRange = ValueRange(computeRandomType(state, maxScalars));
		computeRandomValueRange(state, m_valueRange.asAccess());
	}

	// \todo [2011-03-26 pyry] Vector conversions
//	int						remainingDepth	= state.getShaderParameters().maxExpressionDepth - state.getExpressionDepth();

	const VariableType&		type			= m_valueRange.getType();
	VariableType::Type		baseType		= type.getBaseType();
	int						numScalars		= type.getNumElements();
	int						curScalarNdx	= 0;

	// \todo [2011-03-26 pyry] Separate op for struct constructors!
	DE_ASSERT(type.isFloatOrVec() || type.isIntOrVec() || type.isBoolOrVec());

	bool scalarConversions = state.getProgramParameters().useScalarConversions;

	while (curScalarNdx < numScalars)
	{
		ConstValueRangeAccess comp = m_valueRange.asAccess().component(curScalarNdx);

		if (scalarConversions)
		{
			int					numInTypes = 0;
			VariableType::Type	inTypes[3];

			if (isConversionOk(VariableType::TYPE_FLOAT, baseType, comp))	inTypes[numInTypes++] = VariableType::TYPE_FLOAT;
			if (isConversionOk(VariableType::TYPE_INT, baseType, comp))		inTypes[numInTypes++] = VariableType::TYPE_INT;
			if (isConversionOk(VariableType::TYPE_BOOL, baseType, comp))	inTypes[numInTypes++] = VariableType::TYPE_BOOL;

			DE_ASSERT(numInTypes > 0); // At least nop conversion should be ok

			// Choose random
			VariableType::Type inType = state.getRandom().choose<VariableType::Type>(&inTypes[0], &inTypes[0] + numInTypes);

			// Compute converted value range
			ValueRange inValueRange(VariableType(inType, 1));
			convertValueRange(comp, inValueRange);
			m_inputValueRanges.push_back(inValueRange);

			curScalarNdx += 1;
		}
		else
		{
			m_inputValueRanges.push_back(ValueRange(comp));
			curScalarNdx += 1;
		}
	}
}

ConstructorOp::~ConstructorOp (void)
{
	for (vector<Expression*>::iterator i = m_inputExpressions.begin(); i != m_inputExpressions.end(); i++)
		delete *i;
}

Expression* ConstructorOp::createNextChild (GeneratorState& state)
{
	int					numChildren	= (int)m_inputExpressions.size();
	Expression*			child		= DE_NULL;

	// \note Created in reverse order!
	if (numChildren < (int)m_inputValueRanges.size())
	{
		const ValueRange& inValueRange = m_inputValueRanges[m_inputValueRanges.size()-1-numChildren];
		child = Expression::createRandom(state, inValueRange);
		try
		{
			m_inputExpressions.push_back(child);
		}
		catch (const std::exception&)
		{
			delete child;
			throw;
		}
	}

	return child;
}

float ConstructorOp::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
{
	if (valueRange.getType().isVoid())
		return unusedValueWeight;

	if (!valueRange.getType().isFloatOrVec() && !valueRange.getType().isIntOrVec() && !valueRange.getType().isBoolOrVec())
		return 0.0f;

	if (state.getExpressionDepth() + getTypeConstructorDepth(valueRange.getType()) > state.getShaderParameters().maxExpressionDepth)
		return 0.0f;

	return 1.0f;
}

void ConstructorOp::tokenize (GeneratorState& state, TokenStream& str) const
{
	const VariableType& type = m_valueRange.getType();
	DE_ASSERT(type.getPrecision() == VariableType::PRECISION_NONE);
	type.tokenizeShortType(str);

	str << Token::LEFT_PAREN;

	for (vector<Expression*>::const_reverse_iterator i = m_inputExpressions.rbegin(); i != m_inputExpressions.rend(); i++)
	{
		if (i != m_inputExpressions.rbegin())
			str << Token::COMMA;
		(*i)->tokenize(state, str);
	}

	str << Token::RIGHT_PAREN;
}

void ConstructorOp::evaluate (ExecutionContext& evalCtx)
{
	// Evaluate children
	for (vector<Expression*>::reverse_iterator i = m_inputExpressions.rbegin(); i != m_inputExpressions.rend(); i++)
		(*i)->evaluate(evalCtx);

	// Compute value
	const VariableType& type = m_valueRange.getType();
	m_value.setStorage(type);

	ExecValueAccess	dst				= m_value.getValue(type);
	int				curScalarNdx	= 0;

	for (vector<Expression*>::reverse_iterator i = m_inputExpressions.rbegin(); i != m_inputExpressions.rend(); i++)
	{
		ExecConstValueAccess src = (*i)->getValue();

		for (int elemNdx = 0; elemNdx < src.getType().getNumElements(); elemNdx++)
			convertExecValue(src.component(elemNdx), dst.component(curScalarNdx++));
	}
}

AssignOp::AssignOp (GeneratorState& state, ConstValueRangeAccess valueRange)
	: m_valueRange	(valueRange)
	, m_lvalueExpr	(DE_NULL)
	, m_rvalueExpr	(DE_NULL)
{
	if (m_valueRange.getType().isVoid())
	{
		// Compute random value range
		int		maxScalars		= state.getShaderParameters().maxCombinedVariableScalars - state.getVariableManager().getNumAllocatedScalars();
		bool	useRandomRange	= !state.getVariableManager().hasEntry<IsWritableEntry>() || ((maxScalars > 0) && getWeightedBool(state.getRandom(), 0.1f));

		if (useRandomRange)
		{
			DE_ASSERT(maxScalars > 0);
			m_valueRange = ValueRange(computeRandomType(state, maxScalars));
			computeRandomValueRange(state, m_valueRange.asAccess());
		}
		else
		{
			// Use value range from random entry
			// \todo [2011-02-28 pyry] Give lower weight to entries without range? Choose subtype range?
			const ValueEntry* entry = state.getRandom().choose<const ValueEntry*>(state.getVariableManager().getBegin<IsWritableEntry>(), state.getVariableManager().getEnd<IsWritableEntry>());
			m_valueRange = ValueRange(entry->getValueRange());

			computeRandomValueRangeForInfElements(state, m_valueRange.asAccess());

			DE_ASSERT(state.getVariableManager().hasEntry(IsWritableIntersectingEntry(m_valueRange)));
		}
	}

	IsWritableIntersectingEntry::Iterator first	= state.getVariableManager().getBegin(IsWritableIntersectingEntry(m_valueRange));
	IsWritableIntersectingEntry::Iterator end	= state.getVariableManager().getEnd(IsWritableIntersectingEntry(m_valueRange));

	bool possiblyCreateVar = canAllocateVariable(state, m_valueRange.getType()) &&
							 (first == end || getWeightedBool(state.getRandom(), 0.5f));

	if (!possiblyCreateVar)
	{
		// Find all possible valueranges matching given type and intersecting with valuerange
		// \todo [pyry] Actually collect all ValueRanges, currently operates only on whole variables
		DE_ASSERT(first != end);

		// Try to select one closest to given range but bigger (eg. superset)
		bool supersetExists = false;
		for (IsWritableIntersectingEntry::Iterator i = first; i != end; i++)
		{
			if ((*i)->getValueRange().isSupersetOf(m_valueRange))
			{
				supersetExists = true;
				break;
			}
		}

		if (!supersetExists)
		{
			// Select some other range and compute intersection
			// \todo [2011-02-03 pyry] Use some heuristics to select the range?
			ConstValueRangeAccess selectedRange = state.getRandom().choose<const ValueEntry*>(first, end)->getValueRange();

			ValueRange::computeIntersection(m_valueRange, m_valueRange, selectedRange);
		}
	}
}

AssignOp::~AssignOp (void)
{
	delete m_lvalueExpr;
	delete m_rvalueExpr;
}

float AssignOp::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
{
	if (!valueRange.getType().isVoid() &&
		!canAllocateVariable(state, valueRange.getType()) &&
		!state.getVariableManager().hasEntry(IsWritableIntersectingEntry(valueRange)))
		return 0.0f; // Would require creating a new variable

	if (!valueRange.getType().isVoid() && state.getExpressionDepth() + getTypeConstructorDepth(valueRange.getType()) + 1 >= state.getShaderParameters().maxExpressionDepth)
		return 0.0f;

	if (valueRange.getType().isVoid() &&
		!state.getVariableManager().hasEntry<IsWritableEntry>() &&
		state.getVariableManager().getNumAllocatedScalars() >= state.getShaderParameters().maxCombinedVariableScalars)
		return 0.0f; // Can not allocate a new entry

	if (state.getExpressionDepth() == 0)
		return 4.0f;
	else
		return 0.0f; // \todo [pyry] Fix assign ops
}

Expression* AssignOp::createNextChild (GeneratorState& state)
{
	if (m_lvalueExpr == DE_NULL)
	{
		// Construct lvalue
		// \todo [2011-03-14 pyry] Proper l-value generation:
		//  - pure L-value part is generated first
		//  - variable valuerange is made unbound
		//  - R-value is generated
		//  - R-values in L-value are generated
		m_lvalueExpr = Expression::createRandomLValue(state, m_valueRange);
		return m_lvalueExpr;
	}
	else if (m_rvalueExpr == DE_NULL)
	{
		// Construct value expr
		m_rvalueExpr = Expression::createRandom(state, m_valueRange);
		return m_rvalueExpr;
	}
	else
		return DE_NULL;
}

void AssignOp::tokenize (GeneratorState& state, TokenStream& str) const
{
	m_lvalueExpr->tokenize(state, str);
	str << Token::EQUAL;
	m_rvalueExpr->tokenize(state, str);
}

void AssignOp::evaluate (ExecutionContext& evalCtx)
{
	// Evaluate l-value
	m_lvalueExpr->evaluate(evalCtx);

	// Evaluate value
	m_rvalueExpr->evaluate(evalCtx);
	m_value.setStorage(m_valueRange.getType());
	m_value.getValue(m_valueRange.getType()) = m_rvalueExpr->getValue().value();

	// Assign
	assignMasked(m_lvalueExpr->getLValue(), m_value.getValue(m_valueRange.getType()), evalCtx.getExecutionMask());
}

namespace
{

inline bool isShaderInOutSupportedType (const VariableType& type)
{
	// \todo [2011-03-11 pyry] Float arrays, structs?
	return type.getBaseType() == VariableType::TYPE_FLOAT;
}

Variable* allocateNewVariable (GeneratorState& state, ConstValueRangeAccess valueRange)
{
	Variable* variable = state.getVariableManager().allocate(valueRange.getType());

	// Update value range
	state.getVariableManager().setValue(variable, valueRange);

	// Random storage \todo [pyry] Check that scalar count in uniform/input classes is not exceeded
	static const Variable::Storage storages[] =
	{
		Variable::STORAGE_CONST,
		Variable::STORAGE_UNIFORM,
		Variable::STORAGE_LOCAL,
		Variable::STORAGE_SHADER_IN
	};
	float weights[DE_LENGTH_OF_ARRAY(storages)];

	// Dynamic vs. constant weight.
	float	dynWeight	= computeDynamicRangeWeight(valueRange);
	int		numScalars	= valueRange.getType().getScalarSize();
	bool	uniformOk	= state.getVariableManager().getNumAllocatedUniformScalars() + numScalars <= state.getShaderParameters().maxUniformScalars;
	bool	shaderInOk	= isShaderInOutSupportedType(valueRange.getType()) &&
						  (state.getVariableManager().getNumAllocatedShaderInVariables() + NUM_RESERVED_SHADER_INPUTS < state.getShaderParameters().maxInputVariables);

	weights[0] = de::max(1.0f-dynWeight, 0.1f);
	weights[1] = uniformOk ? dynWeight*0.5f : 0.0f;
	weights[2] = dynWeight;
	weights[3] = shaderInOk ? dynWeight*2.0f : 0.0f;

	state.getVariableManager().setStorage(variable, state.getRandom().chooseWeighted<Variable::Storage>(&storages[0], &storages[DE_LENGTH_OF_ARRAY(storages)], &weights[0]));

	return variable;
}

inline float combineWeight (float curCombinedWeight, float partialWeight)
{
	return curCombinedWeight * partialWeight;
}

float computeEntryReadWeight (ConstValueRangeAccess entryValueRange, ConstValueRangeAccess readValueRange)
{
	const VariableType& type = entryValueRange.getType();
	DE_ASSERT(type == readValueRange.getType());

	float weight = 1.0f;

	switch (type.getBaseType())
	{
		case VariableType::TYPE_FLOAT:
		{
			for (int elemNdx = 0; elemNdx < type.getNumElements(); elemNdx++)
			{
				float entryMin	= entryValueRange.component(elemNdx).getMin().asFloat();
				float entryMax	= entryValueRange.component(elemNdx).getMax().asFloat();
				float readMin	= readValueRange.component(elemNdx).getMin().asFloat();
				float readMax	= readValueRange.component(elemNdx).getMax().asFloat();

				// Check for -inf..inf ranges - they don't bring down the weight.
				if (Scalar::min<float>() == entryMin && Scalar::max<float>() == entryMax)
					continue;

				// Intersection to entry value range length ratio.
				float intersectionMin		= deFloatMax(entryMin, readMin);
				float intersectionMax		= deFloatMin(entryMax, readMax);
				float entryRangeLen			= entryMax - entryMin;
				float readRangeLen			= readMax - readMin;
				float intersectionLen		= intersectionMax - intersectionMin;
				float entryRatio			= (entryRangeLen	> 0.0f) ? (intersectionLen / entryRangeLen)	: 1.0f;
				float readRatio				= (readRangeLen		> 0.0f) ? (intersectionLen / readRangeLen)	: 1.0f;
				float elementWeight			= 0.5f*readRatio + 0.5f*entryRatio;

				weight = combineWeight(weight, elementWeight);
			}
			break;
		}

		case VariableType::TYPE_INT:
		{
			for (int elemNdx = 0; elemNdx < type.getNumElements(); elemNdx++)
			{
				int entryMin	= entryValueRange.component(elemNdx).getMin().asInt();
				int entryMax	= entryValueRange.component(elemNdx).getMax().asInt();
				int readMin		= readValueRange.component(elemNdx).getMin().asInt();
				int readMax		= readValueRange.component(elemNdx).getMax().asInt();

				// Check for -inf..inf ranges - they don't bring down the weight.
				if (Scalar::min<int>() == entryMin && Scalar::max<int>() == entryMax)
					continue;

				// Intersection to entry value range length ratio.
				int intersectionMin			= deMax32(entryMin, readMin);
				int intersectionMax			= deMin32(entryMax, readMax);
				int entryRangeLen			= entryMax - entryMin;
				int readRangeLen			= readMax - readMin;
				int intersectionLen			= intersectionMax - intersectionMin;
				float entryRatio			= (entryRangeLen	> 0) ? ((float)intersectionLen / (float)entryRangeLen)	: 1.0f;
				float readRatio				= (readRangeLen		> 0) ? ((float)intersectionLen / (float)readRangeLen)	: 1.0f;
				float elementWeight			= 0.5f*readRatio + 0.5f*entryRatio;

				weight = combineWeight(weight, elementWeight);
			}
			break;
		}

		case VariableType::TYPE_BOOL:
		{
			// \todo
			break;
		}


		case VariableType::TYPE_ARRAY:
		case VariableType::TYPE_STRUCT:

		default:
			TCU_FAIL("Unsupported type");
	}

	return deFloatMax(weight, 0.01f);
}

} // anonymous

VariableRead::VariableRead (GeneratorState& state, ConstValueRangeAccess valueRange)
{
	if (valueRange.getType().isVoid())
	{
		IsReadableEntry	filter			= IsReadableEntry(state.getExpressionFlags());
		int				maxScalars		= state.getShaderParameters().maxCombinedVariableScalars - state.getVariableManager().getNumAllocatedScalars();
		bool			useRandomRange	= !state.getVariableManager().hasEntry(filter) || ((maxScalars > 0) && getWeightedBool(state.getRandom(), 0.5f));

		if (useRandomRange)
		{
			// Allocate a new variable
			DE_ASSERT(maxScalars > 0);
			ValueRange newVarRange(computeRandomType(state, maxScalars));
			computeRandomValueRange(state, newVarRange.asAccess());

			m_variable = allocateNewVariable(state, newVarRange);
		}
		else
		{
			// Use random entry \todo [pyry] Handle -inf..inf ranges?
			m_variable = state.getRandom().choose<const ValueEntry*>(state.getVariableManager().getBegin(filter), state.getVariableManager().getEnd(filter))->getVariable();
		}
	}
	else
	{
		// Find variable that has value range that intersects with given range
		IsReadableIntersectingEntry::Iterator	first	= state.getVariableManager().getBegin(IsReadableIntersectingEntry(valueRange, state.getExpressionFlags()));
		IsReadableIntersectingEntry::Iterator	end		= state.getVariableManager().getEnd(IsReadableIntersectingEntry(valueRange, state.getExpressionFlags()));

		const float	createOnReadWeight		= 0.5f;
		bool		createVar				= canAllocateVariable(state, valueRange.getType()) && (first == end || getWeightedBool(state.getRandom(), createOnReadWeight));

		if (createVar)
		{
			m_variable = allocateNewVariable(state, valueRange);
		}
		else
		{
			// Copy value entries for computing weights.
			std::vector<const ValueEntry*>	availableVars;
			std::vector<float>				weights;

			std::copy(first, end, std::inserter(availableVars, availableVars.begin()));

			// Compute weights.
			weights.resize(availableVars.size());
			for (int ndx = 0; ndx < (int)availableVars.size(); ndx++)
				weights[ndx] = computeEntryReadWeight(availableVars[ndx]->getValueRange(), valueRange);

			// Select.
			const ValueEntry* entry = state.getRandom().chooseWeighted<const ValueEntry*>(availableVars.begin(), availableVars.end(), weights.begin());
			m_variable = entry->getVariable();

			// Compute intersection
			ValueRange intersection(m_variable->getType());
			ValueRange::computeIntersection(intersection, entry->getValueRange(), valueRange);
			state.getVariableManager().setValue(m_variable, intersection);
		}
	}
}

VariableRead::VariableRead (const Variable* variable)
{
	m_variable = variable;
}

float VariableRead::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
{
	if (valueRange.getType().isVoid())
	{
		if (state.getVariableManager().hasEntry(IsReadableEntry(state.getExpressionFlags())) ||
			state.getVariableManager().getNumAllocatedScalars() < state.getShaderParameters().maxCombinedVariableScalars)
			return unusedValueWeight;
		else
			return 0.0f;
	}

	if (!canAllocateVariable(state, valueRange.getType()) &&
		!state.getVariableManager().hasEntry(IsReadableIntersectingEntry(valueRange, state.getExpressionFlags())))
		return 0.0f;
	else
		return 1.0f;
}

VariableWrite::VariableWrite (GeneratorState& state, ConstValueRangeAccess valueRange)
{
	DE_ASSERT(!valueRange.getType().isVoid());

	// Find variable with range that is superset of given range
	IsWritableSupersetEntry::Iterator	first	= state.getVariableManager().getBegin(IsWritableSupersetEntry(valueRange));
	IsWritableSupersetEntry::Iterator	end		= state.getVariableManager().getEnd(IsWritableSupersetEntry(valueRange));

	const float	createOnAssignWeight	= 0.1f; // Will essentially create an unused variable
	bool		createVar				= canAllocateVariable(state, valueRange.getType()) && (first == end || getWeightedBool(state.getRandom(), createOnAssignWeight));

	if (createVar)
	{
		m_variable = state.getVariableManager().allocate(valueRange.getType());
		// \note Storage will be LOCAL
	}
	else
	{
		// Choose random
		DE_ASSERT(first != end);
		const ValueEntry* entry = state.getRandom().choose<const ValueEntry*>(first, end);
		m_variable = entry->getVariable();
	}

	DE_ASSERT(m_variable);

	// Reset value range.
	const ValueEntry* parentEntry = state.getVariableManager().getParentValue(m_variable);
	if (parentEntry)
	{
		// Use parent value range.
		state.getVariableManager().setValue(m_variable, parentEntry->getValueRange());
	}
	else
	{
		// Use infinite range.
		ValueRange infRange(m_variable->getType());
		setInfiniteRange(infRange);

		state.getVariableManager().setValue(m_variable, infRange);
	}
}

float VariableWrite::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
{
	if (!canAllocateVariable(state, valueRange.getType()) &&
		!state.getVariableManager().hasEntry(IsWritableSupersetEntry(valueRange)))
		return 0.0f;
	else
		return 1.0f;
}

void VariableAccess::evaluate (ExecutionContext& evalCtx)
{
	m_valueAccess = evalCtx.getValue(m_variable);
}

ParenOp::ParenOp (GeneratorState& state, ConstValueRangeAccess valueRange)
	: m_valueRange	(valueRange)
	, m_child		(DE_NULL)
{
	DE_UNREF(state);
}

ParenOp::~ParenOp (void)
{
	delete m_child;
}

Expression* ParenOp::createNextChild (GeneratorState& state)
{
	if (m_child == DE_NULL)
	{
		m_child = Expression::createRandom(state, m_valueRange);
		return m_child;
	}
	else
		return DE_NULL;
}

void ParenOp::tokenize (GeneratorState& state, TokenStream& str) const
{
	str << Token::LEFT_PAREN;
	m_child->tokenize(state, str);
	str << Token::RIGHT_PAREN;
}

float ParenOp::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
{
	if (valueRange.getType().isVoid())
		return state.getExpressionDepth() + 2 <= state.getShaderParameters().maxExpressionDepth ? unusedValueWeight : 0.0f;
	else
	{
		int requiredDepth = 1 + getConservativeValueExprDepth(state, valueRange);
		return state.getExpressionDepth() + requiredDepth <= state.getShaderParameters().maxExpressionDepth ? 1.0f : 0.0f;
	}
}

const int swizzlePrecedence = 2;

SwizzleOp::SwizzleOp (GeneratorState& state, ConstValueRangeAccess valueRange)
	: m_outValueRange		(valueRange)
	, m_numInputElements	(0)
	, m_child				(DE_NULL)
{
	DE_ASSERT(!m_outValueRange.getType().isVoid()); // \todo [2011-06-13 pyry] Void support
	DE_ASSERT(m_outValueRange.getType().isFloatOrVec()	||
			  m_outValueRange.getType().isIntOrVec()	||
			  m_outValueRange.getType().isBoolOrVec());

	m_value.setStorage(m_outValueRange.getType());

	int numOutputElements	= m_outValueRange.getType().getNumElements();

	// \note Swizzle works for vector types only.
	// \todo [2011-06-13 pyry] Use components multiple times.
	m_numInputElements		= state.getRandom().getInt(deMax32(numOutputElements, 2), 4);

	std::set<int> availableElements;
	for (int ndx = 0; ndx < m_numInputElements; ndx++)
		availableElements.insert(ndx);

	// Randomize swizzle.
	for (int elemNdx = 0; elemNdx < (int)DE_LENGTH_OF_ARRAY(m_swizzle); elemNdx++)
	{
		if (elemNdx < numOutputElements)
		{
			int inElemNdx = state.getRandom().choose<int>(availableElements.begin(), availableElements.end());
			availableElements.erase(inElemNdx);
			m_swizzle[elemNdx] = (deUint8)inElemNdx;
		}
		else
			m_swizzle[elemNdx] = 0;
	}
}

SwizzleOp::~SwizzleOp (void)
{
	delete m_child;
}

Expression* SwizzleOp::createNextChild (GeneratorState& state)
{
	if (m_child)
		return DE_NULL;

	// Compute input value range.
	VariableType	inVarType		= VariableType(m_outValueRange.getType().getBaseType(), m_numInputElements);
	ValueRange		inValueRange	= ValueRange(inVarType);

	// Initialize all inputs to -inf..inf
	setInfiniteRange(inValueRange);

	// Compute intersections.
	int numOutputElements = m_outValueRange.getType().getNumElements();
	for (int outElemNdx = 0; outElemNdx < numOutputElements; outElemNdx++)
	{
		int inElemNdx = m_swizzle[outElemNdx];
		ValueRange::computeIntersection(inValueRange.asAccess().component(inElemNdx), inValueRange.asAccess().component(inElemNdx), m_outValueRange.asAccess().component(outElemNdx));
	}

	// Create child.
	state.pushPrecedence(swizzlePrecedence);
	m_child = Expression::createRandom(state, inValueRange);
	state.popPrecedence();

	return m_child;
}

void SwizzleOp::tokenize (GeneratorState& state, TokenStream& str) const
{
	const char*		rgbaSet[]	= { "r", "g", "b", "a" };
	const char*		xyzwSet[]	= { "x", "y", "z", "w" };
	const char*		stpqSet[]	= { "s", "t", "p", "q" };
	const char**	swizzleSet	= DE_NULL;

	switch (state.getRandom().getInt(0, 2))
	{
		case 0: swizzleSet = rgbaSet; break;
		case 1: swizzleSet = xyzwSet; break;
		case 2: swizzleSet = stpqSet; break;
		default: DE_ASSERT(DE_FALSE);
	}

	std::string swizzleStr;
	for (int elemNdx = 0; elemNdx < m_outValueRange.getType().getNumElements(); elemNdx++)
		swizzleStr += swizzleSet[m_swizzle[elemNdx]];

	m_child->tokenize(state, str);
	str << Token::DOT << Token(swizzleStr.c_str());
}

float SwizzleOp::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
{
	if (!state.getProgramParameters().useSwizzle)
		return 0.0f;

	if (state.getPrecedence() < swizzlePrecedence)
		return 0.0f;

	if (!valueRange.getType().isFloatOrVec()	&&
		!valueRange.getType().isIntOrVec()		&&
		!valueRange.getType().isBoolOrVec())
		return 0.0f;

	int availableLevels = state.getShaderParameters().maxExpressionDepth - state.getExpressionDepth();

	// Swizzle + Constructor + Values
	if (availableLevels < 3)
		return 0.0f;

	return 1.0f;
}

void SwizzleOp::evaluate (ExecutionContext& execCtx)
{
	m_child->evaluate(execCtx);

	ExecConstValueAccess	inValue		= m_child->getValue();
	ExecValueAccess			outValue	= m_value.getValue(m_outValueRange.getType());

	for (int outElemNdx = 0; outElemNdx < outValue.getType().getNumElements(); outElemNdx++)
	{
		int inElemNdx = m_swizzle[outElemNdx];
		outValue.component(outElemNdx) = inValue.component(inElemNdx).value();
	}
}

static int countSamplers (const VariableManager& varManager, VariableType::Type samplerType)
{
	int numSamplers = 0;

	IsSamplerEntry::Iterator	i		= varManager.getBegin(IsSamplerEntry(samplerType));
	IsSamplerEntry::Iterator	end		= varManager.getEnd(IsSamplerEntry(samplerType));

	for (; i != end; i++)
		numSamplers += 1;

	return numSamplers;
}

TexLookup::TexLookup (GeneratorState& state, ConstValueRangeAccess valueRange)
	: m_type			(TYPE_LAST)
	, m_coordExpr		(DE_NULL)
	, m_lodBiasExpr		(DE_NULL)
	, m_valueType		(VariableType::TYPE_FLOAT, 4)
	, m_value			(m_valueType)
{
	DE_ASSERT(valueRange.getType() == VariableType(VariableType::TYPE_FLOAT, 4));
	DE_UNREF(valueRange); // Texture output value range is constant.

	// Select type.
	vector<Type> typeCandidates;
	if (state.getShaderParameters().useTexture2D)
	{
		typeCandidates.push_back(TYPE_TEXTURE2D);
		typeCandidates.push_back(TYPE_TEXTURE2D_LOD);
		typeCandidates.push_back(TYPE_TEXTURE2D_PROJ);
		typeCandidates.push_back(TYPE_TEXTURE2D_PROJ_LOD);
	}

	if (state.getShaderParameters().useTextureCube)
	{
		typeCandidates.push_back(TYPE_TEXTURECUBE);
		typeCandidates.push_back(TYPE_TEXTURECUBE_LOD);
	}

	m_type = state.getRandom().choose<Type>(typeCandidates.begin(), typeCandidates.end());

	// Select or allocate sampler.
	VariableType::Type samplerType = VariableType::TYPE_LAST;
	switch (m_type)
	{
		case TYPE_TEXTURE2D:
		case TYPE_TEXTURE2D_LOD:
		case TYPE_TEXTURE2D_PROJ:
		case TYPE_TEXTURE2D_PROJ_LOD:
			samplerType = VariableType::TYPE_SAMPLER_2D;
			break;

		case TYPE_TEXTURECUBE:
		case TYPE_TEXTURECUBE_LOD:
			samplerType = VariableType::TYPE_SAMPLER_CUBE;
			break;

		default:
			DE_ASSERT(DE_FALSE);
	}

	int		sampler2DCount		= countSamplers(state.getVariableManager(), VariableType::TYPE_SAMPLER_2D);
	int		samplerCubeCount	= countSamplers(state.getVariableManager(), VariableType::TYPE_SAMPLER_CUBE);
	bool	canAllocSampler		= sampler2DCount + samplerCubeCount < state.getShaderParameters().maxSamplers;
	bool	hasSampler			= samplerType == VariableType::TYPE_SAMPLER_2D ? (sampler2DCount > 0) : (samplerCubeCount > 0);
	bool	allocSampler		= !hasSampler || (canAllocSampler && state.getRandom().getBool());

	if (allocSampler)
	{
		Variable* sampler = state.getVariableManager().allocate(VariableType(samplerType, 1));
		state.getVariableManager().setStorage(sampler, Variable::STORAGE_UNIFORM); // Samplers are always uniforms.
		m_sampler = sampler;
	}
	else
		m_sampler = state.getRandom().choose<const ValueEntry*>(state.getVariableManager().getBegin(IsSamplerEntry(samplerType)),
															    state.getVariableManager().getEnd(IsSamplerEntry(samplerType)))->getVariable();
}

TexLookup::~TexLookup (void)
{
	delete m_coordExpr;
	delete m_lodBiasExpr;
}

Expression* TexLookup::createNextChild (GeneratorState& state)
{
	bool hasLodBias		= m_type == TYPE_TEXTURE2D_LOD ||
						  m_type == TYPE_TEXTURE2D_PROJ_LOD ||
						  m_type == TYPE_TEXTURECUBE_LOD;

	if (hasLodBias && !m_lodBiasExpr)
	{
		ValueRange lodRange(VariableType(VariableType::TYPE_FLOAT, 1));
		setInfiniteRange(lodRange); // Any value is valid.

		m_lodBiasExpr = Expression::createRandom(state, lodRange);
		return m_lodBiasExpr;
	}

	if (!m_coordExpr)
	{
		if (m_type == TYPE_TEXTURECUBE || m_type == TYPE_TEXTURECUBE_LOD)
		{
			// Make sure major axis selection can be done.
			int majorAxisNdx = state.getRandom().getInt(0, 2);

			ValueRange coordRange(VariableType(VariableType::TYPE_FLOAT, 3));

			for (int ndx = 0; ndx < 3; ndx++)
			{
				if (ndx == majorAxisNdx)
				{
					bool neg = state.getRandom().getBool();
					coordRange.getMin().component(ndx) = neg ? -4.0f	: 2.25f;
					coordRange.getMax().component(ndx) = neg ? -2.25f	: 4.0f;
				}
				else
				{
					coordRange.getMin().component(ndx) = -2.0f;
					coordRange.getMax().component(ndx) =  2.0f;
				}
			}

			m_coordExpr = Expression::createRandom(state, coordRange);
		}
		else
		{
			bool	isProj				= m_type == TYPE_TEXTURE2D_PROJ || m_type == TYPE_TEXTURE2D_PROJ_LOD;
			int		coordScalarSize		= isProj ? 3 : 2;

			ValueRange coordRange(VariableType(VariableType::TYPE_FLOAT, coordScalarSize));
			setInfiniteRange(coordRange); // Initialize base range with -inf..inf

			if (isProj)
			{
				// w coordinate must be something sane, and not 0.
				bool neg = state.getRandom().getBool();
				coordRange.getMin().component(2) = neg ? -4.0f  : 0.25f;
				coordRange.getMax().component(2) = neg ? -0.25f : 4.0f;
			}

			m_coordExpr = Expression::createRandom(state, coordRange);
		}

		DE_ASSERT(m_coordExpr);
		return m_coordExpr;
	}

	return DE_NULL; // Done.
}

void TexLookup::tokenize (GeneratorState& state, TokenStream& str) const
{
	bool isVertex = state.getShader().getType() == Shader::TYPE_VERTEX;

	if (state.getProgramParameters().version == VERSION_300)
	{
		switch (m_type)
		{
			case TYPE_TEXTURE2D:			str << "texture";										break;
			case TYPE_TEXTURE2D_LOD:		str << (isVertex ? "textureLod" : "texture");			break;
			case TYPE_TEXTURE2D_PROJ:		str << "textureProj";									break;
			case TYPE_TEXTURE2D_PROJ_LOD:	str << (isVertex ? "textureProjLod" : "textureProj");	break;
			case TYPE_TEXTURECUBE:			str << "texture";										break;
			case TYPE_TEXTURECUBE_LOD:		str << (isVertex ? "textureLod" : "texture");			break;
			default:
				DE_ASSERT(DE_FALSE);
		}
	}
	else
	{
		switch (m_type)
		{
			case TYPE_TEXTURE2D:			str << "texture2D";											break;
			case TYPE_TEXTURE2D_LOD:		str << (isVertex ? "texture2DLod" : "texture2D");			break;
			case TYPE_TEXTURE2D_PROJ:		str << "texture2DProj";										break;
			case TYPE_TEXTURE2D_PROJ_LOD:	str << (isVertex ? "texture2DProjLod" : "texture2DProj");	break;
			case TYPE_TEXTURECUBE:			str << "textureCube";										break;
			case TYPE_TEXTURECUBE_LOD:		str << (isVertex ? "textureCubeLod" : "textureCube");		break;
			default:
				DE_ASSERT(DE_FALSE);
		}
	}

	str << Token::LEFT_PAREN;
	str << m_sampler->getName();
	str << Token::COMMA;
	m_coordExpr->tokenize(state, str);

	if (m_lodBiasExpr)
	{
		str << Token::COMMA;
		m_lodBiasExpr->tokenize(state, str);
	}

	str << Token::RIGHT_PAREN;
}

float TexLookup::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange)
{
	if (state.getShaderParameters().texLookupBaseWeight <= 0.0f)
		return 0.0f;

	int availableLevels = state.getShaderParameters().maxExpressionDepth - state.getExpressionDepth();

	// Lookup + Constructor + Values
	if (availableLevels < 3)
		return 0.0f;

	if (state.getExpressionFlags() & (CONST_EXPR|NO_VAR_ALLOCATION))
		return 0.0f;

	if (valueRange.getType() != VariableType(VariableType::TYPE_FLOAT, 4))
		return 0.0f;

	ValueRange texOutputRange(VariableType(VariableType::TYPE_FLOAT, 4));
	for (int ndx = 0; ndx < 4; ndx++)
	{
		texOutputRange.getMin().component(ndx) = 0.0f;
		texOutputRange.getMax().component(ndx) = 1.0f;
	}

	if (!valueRange.isSupersetOf(texOutputRange))
		return 0.0f;

	return state.getShaderParameters().texLookupBaseWeight;
}

void TexLookup::evaluate (ExecutionContext& execCtx)
{
	// Evaluate coord and bias.
	m_coordExpr->evaluate(execCtx);
	if (m_lodBiasExpr)
		m_lodBiasExpr->evaluate(execCtx);

	ExecConstValueAccess	coords	= m_coordExpr->getValue();
	ExecValueAccess			dst		= m_value.getValue(m_valueType);

	switch (m_type)
	{
		case TYPE_TEXTURE2D:
		{
			const Sampler2D& tex = execCtx.getSampler2D(m_sampler);
			for (int i = 0; i < EXEC_VEC_WIDTH; i++)
			{
				float		s	= coords.component(0).asFloat(i);
				float		t	= coords.component(1).asFloat(i);
				tcu::Vec4	p	= tex.sample(s, t, 0.0f);

				for (int comp = 0; comp < 4; comp++)
					dst.component(comp).asFloat(i) = p[comp];
			}
			break;
		}

		case TYPE_TEXTURE2D_LOD:
		{
			ExecConstValueAccess	lod		= m_lodBiasExpr->getValue();
			const Sampler2D&		tex		= execCtx.getSampler2D(m_sampler);
			for (int i = 0; i < EXEC_VEC_WIDTH; i++)
			{
				float		s	= coords.component(0).asFloat(i);
				float		t	= coords.component(1).asFloat(i);
				float		l	= lod.component(0).asFloat(i);
				tcu::Vec4	p	= tex.sample(s, t, l);

				for (int comp = 0; comp < 4; comp++)
					dst.component(comp).asFloat(i) = p[comp];
			}
			break;
		}

		case TYPE_TEXTURE2D_PROJ:
		{
			const Sampler2D& tex = execCtx.getSampler2D(m_sampler);
			for (int i = 0; i < EXEC_VEC_WIDTH; i++)
			{
				float		s	= coords.component(0).asFloat(i);
				float		t	= coords.component(1).asFloat(i);
				float		w	= coords.component(2).asFloat(i);
				tcu::Vec4	p	= tex.sample(s/w, t/w, 0.0f);

				for (int comp = 0; comp < 4; comp++)
					dst.component(comp).asFloat(i) = p[comp];
			}
			break;
		}

		case TYPE_TEXTURE2D_PROJ_LOD:
		{
			ExecConstValueAccess	lod		= m_lodBiasExpr->getValue();
			const Sampler2D&		tex		= execCtx.getSampler2D(m_sampler);
			for (int i = 0; i < EXEC_VEC_WIDTH; i++)
			{
				float		s	= coords.component(0).asFloat(i);
				float		t	= coords.component(1).asFloat(i);
				float		w	= coords.component(2).asFloat(i);
				float		l	= lod.component(0).asFloat(i);
				tcu::Vec4	p	= tex.sample(s/w, t/w, l);

				for (int comp = 0; comp < 4; comp++)
					dst.component(comp).asFloat(i) = p[comp];
			}
			break;
		}

		case TYPE_TEXTURECUBE:
		{
			const SamplerCube& tex = execCtx.getSamplerCube(m_sampler);
			for (int i = 0; i < EXEC_VEC_WIDTH; i++)
			{
				float		s	= coords.component(0).asFloat(i);
				float		t	= coords.component(1).asFloat(i);
				float		r	= coords.component(2).asFloat(i);
				tcu::Vec4	p	= tex.sample(s, t, r, 0.0f);

				for (int comp = 0; comp < 4; comp++)
					dst.component(comp).asFloat(i) = p[comp];
			}
			break;
		}

		case TYPE_TEXTURECUBE_LOD:
		{
			ExecConstValueAccess	lod		= m_lodBiasExpr->getValue();
			const SamplerCube&		tex		= execCtx.getSamplerCube(m_sampler);
			for (int i = 0; i < EXEC_VEC_WIDTH; i++)
			{
				float		s	= coords.component(0).asFloat(i);
				float		t	= coords.component(1).asFloat(i);
				float		r	= coords.component(2).asFloat(i);
				float		l	= lod.component(0).asFloat(i);
				tcu::Vec4	p	= tex.sample(s, t, r, l);

				for (int comp = 0; comp < 4; comp++)
					dst.component(comp).asFloat(i) = p[comp];
			}
			break;
		}

		default:
			DE_ASSERT(DE_FALSE);
	}
}

} // rsg
