/*-------------------------------------------------------------------------
 * 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*(float)minStep;
				float maxVal	= minVal + step*(float)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;

	const float		value	= deFloatClamp(minVal + step*(float)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 - (float)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 bool		convert<bool, bool>		(bool src)	{ return src;							}
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.asAccess())));
		}
	}

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

	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.asAccess()))
			{
				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.asAccess(), m_valueRange.asAccess(), 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.asAccess());
		return m_lvalueExpr;
	}
	else if (m_rvalueExpr == DE_NULL)
	{
		// Construct value expr
		m_rvalueExpr = Expression::createRandom(state, m_valueRange.asAccess());
		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);
				deInt64 entryRangeLen			= (deInt64)entryMax - (deInt64)entryMin;
				deInt64	readRangeLen			= (deInt64)readMax - (deInt64)readMin;
				deInt64	intersectionLen			= (deInt64)intersectionMax - (deInt64)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.asAccess());
		}
		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.asAccess());
		}
	}
}

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.asAccess());
	}
}

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.asAccess());
		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.asAccess());
	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.asAccess());
		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.asAccess());
		}
		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.asAccess());
		}

		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.asAccess()))
		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
