#ifndef __VALUE_H__
#define __VALUE_H__

#include "Common.h"
#include "Symbol.h"
#include "Stream.h"
#include "DateTime.h"

namespace AScript {

class Expr;
class ObjectBase;
class Environment;
class Module;
class Function;
class Class;
class Object;
class Object_Function;
class Object_String;
class Object_Binary;
class Object_BinaryPtr;
class Object_List;
class Object_Matrix;
class Object_Dict;
class Object_DateTime;
class Object_TimeDelta;
class Object_Iterator;
class Object_Stream;
class Object_Expr;
class Object_Environment;
class Object_Error;
class Object_URI;
class Object_Semaphore;
class Object_Struct;
class Object_Image;
class Object_Color;
class Object_Palette;
class Object_Audio;
class Object_Codec;

class ValueList;
class ValueDict;

class Iterator;

//-----------------------------------------------------------------------------
// ValueType
//-----------------------------------------------------------------------------
typedef unsigned short ValueType;

#define AScript_VTYPE(name) \
(ValueTypePool::GetInstance()->_pValueTypeInfo_##name->GetValueType())

#define AScript_VTYPEInfo(name) \
(ValueTypePool::GetInstance()->_pValueTypeInfo_##name)

#define AScript_DeclareVTYPE(name) \
ValueTypeInfo *_pValueTypeInfo_##name

#define AScript_RealizeVTYPE(name, str) \
env.AssignValueType(_pValueTypeInfo_##name = \
			ValueTypePool::GetInstance()->Add(Symbol::Add(str)))

#define AScript_PrivClass(name) \
(Class_##name::_pValueTypeInfo->GetClass())

#define AScript_PrivVTYPE(name) \
(Class_##name::_pValueTypeInfo->GetValueType())

#define AScript_ImplementClass(name) \
Class_##name::Class_##name(Environment *pEnvOuter) : Class(pEnvOuter)

#define AScript_DeclarePrivClass(name) \
class DLLEXPORT Class_##name : public Class { \
public: \
	Class_##name(Environment *pEnvOuter); \
	virtual bool CastFrom(Environment &env, Signal sig, Value &value); \
	virtual bool CastTo(Environment &env, Signal sig, Value &value, ValueType valType); \
public: \
	static ValueTypeInfo *_pValueTypeInfo; \
};

#define AScript_ImplementPrivClass(name) \
ValueTypeInfo *Class_##name::_pValueTypeInfo = NULL; \
bool Class_##name::CastFrom(Environment &env, Signal sig, Value &value) { return false; } \
bool Class_##name::CastTo(Environment &env, Signal sig, Value &value, ValueType valType) { return false; } \
Class_##name::Class_##name(Environment *pEnvOuter) : Class(pEnvOuter)

#define AScript_ImplementPrivClassWithCast(name) \
ValueTypeInfo *Class_##name::_pValueTypeInfo = NULL; \
Class_##name::Class_##name(Environment *pEnvOuter) : Class(pEnvOuter)

#define AScript_ImplementCastFrom(name) \
bool Class_##name::CastFrom(Environment &env, Signal sig, Value &value)

#define AScript_ImplementCastTo(name) \
bool Class_##name::CastTo(Environment &env, Signal sig, Value &value, ValueType valType)

#define AScript_RealizePrivClass(name, str, pClassBase) \
env.AssignValueType(Class_##name::_pValueTypeInfo = \
			ValueTypePool::GetInstance()->Add(Symbol::Add(str))); \
Class_##name::_pValueTypeInfo->SetClass(new Class_##name(pClassBase))

// nil / undefined
#define VTYPE_Nil			static_cast<ValueType>(0)
#define VTYPE_Undefined		static_cast<ValueType>(1)
// primitive types
#define VTYPE_Symbol		AScript_VTYPE(Symbol)
#define VTYPE_Boolean		AScript_VTYPE(Boolean)
#define VTYPE_Number		AScript_VTYPE(Number)
#define VTYPE_Complex		AScript_VTYPE(Complex)
// for declaration
#define VTYPE_Quote			AScript_VTYPE(Quote)
#define VTYPE_Any			AScript_VTYPE(Any)
// container types
#define VTYPE_Module		AScript_VTYPE(Module)
#define VTYPE_Class			AScript_VTYPE(Class)
// object types
#define VTYPE_Object		AScript_VTYPE(Object)
#define VTYPE_Function		AScript_VTYPE(Function)
#define VTYPE_String		AScript_VTYPE(String)
#define VTYPE_StringEmb		AScript_VTYPE(StringEmb)
#define VTYPE_Binary		AScript_VTYPE(Binary)
#define VTYPE_BinaryEmb		AScript_VTYPE(BinaryEmb)
#define VTYPE_BinaryPtr		AScript_VTYPE(BinaryPtr)
#define VTYPE_List			AScript_VTYPE(List)
#define VTYPE_Matrix		AScript_VTYPE(Matrix)
#define VTYPE_Dict			AScript_VTYPE(Dict)
#define VTYPE_Stream		AScript_VTYPE(Stream)
#define VTYPE_DateTime		AScript_VTYPE(DateTime)
#define VTYPE_TimeDelta		AScript_VTYPE(TimeDelta)
#define VTYPE_Iterator		AScript_VTYPE(Iterator)
#define VTYPE_Expr			AScript_VTYPE(Expr)
#define VTYPE_Environment	AScript_VTYPE(Environment)
#define VTYPE_Error			AScript_VTYPE(Error)
#define VTYPE_URI			AScript_VTYPE(URI)
#define VTYPE_Semaphore		AScript_VTYPE(Semaphore)
#define VTYPE_Struct		AScript_VTYPE(Struct)
#define VTYPE_Image			AScript_VTYPE(Image)
#define VTYPE_Color			AScript_VTYPE(Color)
#define VTYPE_Palette		AScript_VTYPE(Palette)
#define VTYPE_Audio			AScript_VTYPE(Audio)
#define VTYPE_Codec			AScript_VTYPE(Codec)

//-----------------------------------------------------------------------------
// ValueTypeInfo
//-----------------------------------------------------------------------------
class DLLDECLARE ValueTypeInfo {
private:
	ValueType _valType;
	const Symbol *_pSymbol;
	Class *_pClass;
public:
	inline ValueTypeInfo(ValueType valType, const Symbol *pSymbol, Class *pClass) :
					_valType(valType), _pSymbol(pSymbol), _pClass(pClass) {}
	~ValueTypeInfo();
	inline static void Delete(ValueTypeInfo *pValTypeInfo) { delete pValTypeInfo; }
	inline const Symbol *GetSymbol() const { return _pSymbol; }
	inline ValueType GetValueType() const { return _valType; }
	inline Class *GetClass() const { return _pClass; }
	void SetClass(Class *pClass);
};

//-----------------------------------------------------------------------------
// ValueTypeMap
//-----------------------------------------------------------------------------
typedef std::map<const Symbol *, const ValueTypeInfo *,
									Symbol::KeyCompare_UniqNumber> ValueTypeMap;

//-----------------------------------------------------------------------------
// ValueTypeList
//-----------------------------------------------------------------------------
typedef std::vector<ValueTypeInfo *> ValueTypeList;

//-----------------------------------------------------------------------------
// ValueTypePool
//-----------------------------------------------------------------------------
class DLLDECLARE ValueTypePool {
public:
	// primitive types
	AScript_DeclareVTYPE(Nil);
	AScript_DeclareVTYPE(Undefined);
	AScript_DeclareVTYPE(Symbol);
	AScript_DeclareVTYPE(Boolean);
	AScript_DeclareVTYPE(Number);
	AScript_DeclareVTYPE(Complex);
	// for declaration
	AScript_DeclareVTYPE(Quote);
	AScript_DeclareVTYPE(Any);
	// container types
	AScript_DeclareVTYPE(Module);
	AScript_DeclareVTYPE(Class);
	// object types
	AScript_DeclareVTYPE(Object);
	AScript_DeclareVTYPE(Function);
	AScript_DeclareVTYPE(String);
	AScript_DeclareVTYPE(StringEmb);
	AScript_DeclareVTYPE(Binary);
	AScript_DeclareVTYPE(BinaryEmb);
	AScript_DeclareVTYPE(BinaryPtr);
	AScript_DeclareVTYPE(List);
	AScript_DeclareVTYPE(Matrix);
	AScript_DeclareVTYPE(Dict);
	AScript_DeclareVTYPE(Stream);
	AScript_DeclareVTYPE(DateTime);
	AScript_DeclareVTYPE(TimeDelta);
	AScript_DeclareVTYPE(Iterator);
	AScript_DeclareVTYPE(Expr);
	AScript_DeclareVTYPE(Environment);
	AScript_DeclareVTYPE(Error);
	AScript_DeclareVTYPE(URI);
	AScript_DeclareVTYPE(Semaphore);
	AScript_DeclareVTYPE(Struct);
	AScript_DeclareVTYPE(Image);
	AScript_DeclareVTYPE(Color);
	AScript_DeclareVTYPE(Palette);
	AScript_DeclareVTYPE(Audio);
	AScript_DeclareVTYPE(Codec);
private:
	static ValueTypePool *_pInst;
	ValueTypeList _valueTypeList;
private:
	inline ValueTypePool() {}
public:
	~ValueTypePool();
	static void Initialize(Environment &env);
	static ValueTypePool *GetInstance();
	inline ValueTypeList &GetList() { return _valueTypeList; }
	inline const ValueTypeList &GetList() const { return _valueTypeList; }
	ValueTypeInfo *Add(const Symbol *pSymbol);
	ValueTypeInfo *Lookup(ValueType valType);
private:
	void _Initialize(Environment &env);
private:
	inline ValueTypePool(const ValueTypePool &valTypeInfoPool) {}
	inline void operator=(const ValueTypePool &valTypeInfoPool) {}
};

inline const Symbol *GetValueTypeSymbol(ValueType valType)
{
	return ValueTypePool::GetInstance()->Lookup(valType)->GetSymbol();
}

//-----------------------------------------------------------------------------
// ValueVisitor
//-----------------------------------------------------------------------------
class ValueVisitor {
public:
	virtual void Visit(Signal sig, const Value &value) = 0;
};

//-----------------------------------------------------------------------------
// Value
//-----------------------------------------------------------------------------
class DLLDECLARE Value {
public:
	struct KeyCompare {
		inline bool operator()(const Value &value1, const Value &value2) const {
			return Compare(value1, value2) < 0;
		}
	};
private:
	unsigned short _valType;
	char _ownFlag;
	union {
		Number num;				// VTYPE_Number
		bool flag;				// VTYPE_Boolean
		const Symbol *pSymbol;	// VTYPE_Symbol
		Complex *pComp;			// VTYPE_Complex
		Module *pModule;		// VTYPE_Module
		Class *pClass;			// VTYPE_Class
		Object *pObj;			// objects
	} _u;
private:
	static const Complex _compZero;
public:
	static const Value Null;
	static const Value Undefined;
public:
	Value(const Value &value);
	~Value();
	inline Value(ValueType valType, bool ownFlag) :
										_valType(valType), _ownFlag(ownFlag) {}
	// VTYPE_Nil
	inline Value() : _valType(VTYPE_Nil), _ownFlag(true) {}
	// VTYPE_Module
	inline Value(Module *pModule, bool ownFlag = true) :
										_valType(VTYPE_Module), _ownFlag(ownFlag) {
		_u.pModule = pModule;
	}
	// VTYPE_Class
	inline Value(Class *pClass, bool ownFlag = true) :
										_valType(VTYPE_Class), _ownFlag(ownFlag) {
		_u.pClass = pClass;
	}
	// VTYPE_Object etc
	Value(Object *pObj, bool ownFlag = true);
	// VTYPE_Number
	inline Value(Number num) : _valType(VTYPE_Number), _ownFlag(true) {
		_u.num = num;
	}
	inline Value(int num) : _valType(VTYPE_Number), _ownFlag(true) {
		_u.num = static_cast<Number>(num);
	}
	inline Value(unsigned int num) : _valType(VTYPE_Number), _ownFlag(true) {
		_u.num = static_cast<Number>(num);
	}
	inline Value(char num) : _valType(VTYPE_Number), _ownFlag(true) {
		_u.num = static_cast<Number>(num);
	}
	inline Value(unsigned char num) : _valType(VTYPE_Number), _ownFlag(true) {
		_u.num = static_cast<Number>(num);
	}
	inline Value(short num) : _valType(VTYPE_Number), _ownFlag(true) {
		_u.num = static_cast<Number>(num);
	}
	inline Value(unsigned short num) : _valType(VTYPE_Number), _ownFlag(true) {
		_u.num = static_cast<Number>(num);
	}
	inline Value(long num) : _valType(VTYPE_Number), _ownFlag(true) {
		_u.num = static_cast<Number>(num);
	}
	inline Value(unsigned long num) : _valType(VTYPE_Number), _ownFlag(true) {
		_u.num = static_cast<Number>(num);
	}
	// VTYPE_Boolean
	inline Value(bool flag) : _valType(VTYPE_Boolean), _ownFlag(true) {
		_u.flag = flag;
	}
	// VTYPE_Symbol
	inline Value(const Symbol *pSymbol) : _valType(VTYPE_Symbol), _ownFlag(true) {
		_u.pSymbol = pSymbol;
	}
	// VTYPE_Complex
	inline Value(const Complex &comp) : _valType(VTYPE_Complex), _ownFlag(true) {
		_u.pComp = new Complex(comp);
	}
	// VTYPE_String, VTYPE_Binary, VTYPE_StringEmb, VTYPE_BinaryEmb
	Value(Environment &env, const char *str);
	Value(Environment &env, const char *str, size_t len);
	Value(Environment &env, ValueType valType, const char *str);
	Value(Environment &env, ValueType valType, const char *str, size_t len);
	// VTYPE_Iterator
	Value(Environment &env, Iterator *pIterator);
	// VTYPE_Stream
	Value(Environment &env, Stream *pStream);
	// VTYPE_Expr
	Value(Environment &env, Expr *pExpr);
	// VTYPE_Function
	Value(Environment &env, Function *pFunc, const Value &valueSelf);
	// VTYPE_DateTime
	Value(Environment &env, const DateTime &dateTime);
	// VTYPE_TimeDelta
	Value(Environment &env, const TimeDelta &timeDelta);
	Value &operator=(const Value &value);
	const char *GetTypeName() const;
	inline ValueType GetType() const { return _valType; }
	inline bool IsType(ValueType valType) const { return _valType == valType;	}
	inline bool IsObject() const			{ return _valType >= VTYPE_Object;	}
	inline bool IsPrimitive() const			{ return _valType <= VTYPE_Complex;	}
	inline bool IsInvalid() const			{ return IsType(VTYPE_Nil) || IsType(VTYPE_Undefined); }
	inline bool IsUndefined() const			{ return IsType(VTYPE_Undefined);	}
	inline bool IsValid() const				{ return !IsInvalid();				}
	inline bool IsDefined() const			{ return !IsUndefined();			}
	inline bool IsSymbol() const			{ return IsType(VTYPE_Symbol);		}
	inline bool IsBoolean() const			{ return IsType(VTYPE_Boolean);		}
	inline bool IsNumber() const			{ return IsType(VTYPE_Number);		}
	inline bool IsComplex() const			{ return IsType(VTYPE_Complex);		}
	inline bool IsModule() const			{ return IsType(VTYPE_Module);		}
	inline bool IsClass() const				{ return IsType(VTYPE_Class);		}
	inline bool IsGenericObject() const		{ return IsType(VTYPE_Object);		}
	inline bool IsFunction() const			{ return IsType(VTYPE_Function);	}
	inline bool IsString() const			{ return IsType(VTYPE_String);		}
	inline bool IsStringEmb() const			{ return IsType(VTYPE_StringEmb);	}
	inline bool IsBinary() const			{ return IsType(VTYPE_Binary);		}
	inline bool IsBinaryEmb() const			{ return IsType(VTYPE_BinaryEmb);	}
	inline bool IsBinaryPtr() const			{ return IsType(VTYPE_BinaryPtr);	}
	inline bool IsList() const				{ return IsType(VTYPE_List);		}
	inline bool IsMatrix() const			{ return IsType(VTYPE_Matrix);		}
	inline bool IsDict() const				{ return IsType(VTYPE_Dict);		}
	inline bool IsStream() const			{ return IsType(VTYPE_Stream);		}
	inline bool IsDateTime() const			{ return IsType(VTYPE_DateTime);	}
	inline bool IsTimeDelta() const			{ return IsType(VTYPE_TimeDelta);	}
	inline bool IsIterator() const			{ return IsType(VTYPE_Iterator);	}
	inline bool IsExpr() const				{ return IsType(VTYPE_Expr);		}
	inline bool IsEnvironment() const		{ return IsType(VTYPE_Environment);	}
	inline bool IsError() const				{ return IsType(VTYPE_Error);		}
	inline bool IsURI() const				{ return IsType(VTYPE_URI);			}
	inline bool IsSemaphore() const			{ return IsType(VTYPE_Semaphore);	}
	inline bool IsStruct() const			{ return IsType(VTYPE_Struct);		}
	inline bool IsImage() const				{ return IsType(VTYPE_Image);		}
	inline bool IsColor() const				{ return IsType(VTYPE_Color);		}
	inline bool IsPalette() const			{ return IsType(VTYPE_Palette);		}
	inline bool IsAudio() const				{ return IsType(VTYPE_Audio);		}
	inline bool IsCodec() const				{ return IsType(VTYPE_Codec);		}
	inline bool IsListOrIterator() const	{ return IsList() || IsIterator();	}
	inline bool IsNumberOrComplex() const	{ return IsNumber() || IsComplex();	}
	inline void SetSymbol(const Symbol *pSymbol) {
		FreeResource(); _valType = VTYPE_Symbol, _u.pSymbol = pSymbol;
	}
	inline void SetBoolean(bool flag) {
		FreeResource(); _valType = VTYPE_Boolean, _u.flag = flag;
	}
	inline void SetNumber(Number num) {
		FreeResource(); _valType = VTYPE_Number, _u.num = num;
	}
	inline void SetComplex(const Complex &comp) {
		FreeResource();
		if (comp.imag() == 0.) {
			 _valType = VTYPE_Number, _u.num = comp.real();
		} else {
			 _valType = VTYPE_Complex, _u.pComp = new Complex(comp);
		}
	}
	inline Number GetNumber() const {
		return IsNumber()? _u.num :
				IsBoolean()? (_u.flag? 1. : 0.) :
				IsString()? ::strtod(GetString(), NULL) : 0.;
	}
	// VTYPE_Symbol
	inline const Symbol *GetSymbol() const {
		return IsSymbol()? _u.pSymbol : NULL;
	}
	// VTYPE_Boolean
	inline bool GetBoolean() const {
		return IsBoolean()? _u.flag : IsValid();
	}
	// VTYPE_Number
	inline int GetInt() const				{ return static_cast<int>(GetNumber());				}
	inline unsigned int GetUInt() const		{ return static_cast<unsigned int>(GetNumber());	}
	inline size_t GetSizeT() const			{ return static_cast<size_t>(GetNumber());			}
	inline char GetChar() const				{ return static_cast<char>(GetNumber());			}
	inline unsigned char GetUChar() const	{ return static_cast<unsigned char>(GetNumber());	}
	inline short GetShort() const			{ return static_cast<short>(GetNumber());			}
	inline unsigned short GetUShort() const	{ return static_cast<unsigned short>(GetNumber());	}
	inline long GetLong() const				{ return static_cast<long>(GetNumber());			}
	inline unsigned long GetULong() const	{ return static_cast<unsigned long>(GetNumber());	}
	inline float GetFloat() const			{ return static_cast<float>(GetNumber());			}
	inline double GetDouble() const			{ return static_cast<double>(GetNumber());			}
	// VTYPE_Complex
	inline Complex GetComplex() const {
		return IsComplex()? *_u.pComp : IsNumber()? Complex(GetNumber()) : _compZero;
	}
	// VTYPE_Module
	inline Module *GetModule() { return IsModule()? _u.pModule : NULL; }
	inline const Module *GetModule() const { return IsModule()? _u.pModule : NULL; }
	// VTYPE_Class
	inline Class *GetClass() { return IsClass()? _u.pClass : NULL; }
	inline const Class *GetClass() const { return IsClass()? _u.pClass : NULL; }
	// VTYPE_Function
	Function *GetFunction();
	Object_Function *GetFunctionObj();
	inline const Function *GetFunction() const {
		return const_cast<Value *>(this)->GetFunction();
	}
	inline const Object_Function *GetFunctionObj() const {
		return const_cast<Value *>(this)->GetFunctionObj();
	}
	// VTYPE_String
	const char *GetString() const;
	const String &GetStringSTL() const;
	Object_String *GetStringObj();
	Object_String *GetStringObj() const;
	// VTYPE_Binary
	const Binary &GetBinary() const;
	// VTYPE_BinaryPtr
	Object_BinaryPtr *GetBinaryPtr() const;
	// VTYPE_List
	ValueList &GetList();
	const ValueList &GetList() const;
	Object_List *GetListObj();
	Object_List *GetListObj() const;
	// VTYPE_Matrix
	Object_Matrix *GetMatrixObj();
	Object_Matrix *GetMatrixObj() const;
	// VTYPE_Dict
	ValueDict &GetDict();
	const ValueDict &GetDict() const;
	// VTYPE_Stream
	Stream &GetStream() const;
	Object_Stream *GetStreamObj() const;
	// VTYPE_DateTime
	const DateTime &GetDateTime() const;
	// VTYPE_TimeDelta
	const TimeDelta &GetTimeDelta() const;
	// VTYPE_Iterator
	Iterator *GetIterator() const;
	// VTYPE_Expr
	const Expr *GetExpr() const;
	// VTYPE_Image
	Object_Image *GetImageObj();
	Object_Image *GetImageObj() const;
	// VTYPE_Color
	Object_Color *GetColorObj();
	Object_Color *GetColorObj() const;
	// VTYPE_Palette
	Object_Palette *GetPaletteObj();
	Object_Palette *GetPaletteObj() const;
	//-----------------------
	bool PropDir(Environment &env, Signal sig, SymbolSet &symbols);
	ErrorType GetErrorType() const;
	bool IsFlatList() const;
	bool IsInstanceOf(ValueType valType);
	ObjectBase *ExtractObject(Signal sig);
	inline ObjectBase *ExtractObject(Signal sig) const {
		return const_cast<Value *>(this)->ExtractObject(sig);
	}
	Expr *CloneExpr() const;
	inline Object *GetObject() { return IsObject()? _u.pObj : NULL; }
	inline Object *GetObject() const { return IsObject()? _u.pObj : NULL; }
	ObjectBase *GetObjectBase();
	Iterator *CreateIterator(Signal sig) const;
	String ToString(Signal sig, bool exprFlag = true) const;
	Number ToNumber(bool allowPartFlag, bool &successFlag) const;
	void Accept(Signal sig, ValueVisitor &visitor) const;
	void InitAsModule(Module *pModule);
	void InitAsClass(Class *pClass);
	void InitAsObject(Object *pObj);
	ValueList &InitAsList(Environment &env);
	ValueList &InitAsList(Environment &env, size_t n, const Value &value);
	Object_Matrix *InitAsMatrix(Environment &env,
								int nRows, int nCols, const Value &valueElem);
	Object_Matrix *InitAsMatrix(Environment &env, Signal sig, const ValueList &valList);
	ValueDict &InitAsDict(Environment &env);
	Object_Binary *InitAsBinary(Environment &env);
	Object_Binary *InitAsBinary(Environment &env, const Binary &binary);
	Object_Binary *InitAsBinary(Environment &env, const char *buff, size_t size);
	Object_BinaryPtr *InitAsBinaryPtr(Environment &env,
							Object_Binary *pObjBinary, size_t offset);
	void InitAsExpr(Environment &env, Expr *pExpr);
	void InitAsIterator(Environment &env, Iterator *pIterator);
	void InitAsEnvironment(Environment &env);
public:
	static int Compare(const Value &value1, const Value &value2);
	inline bool operator<(const Value &value) const {
		return Compare(*this, value) < 0;
	}
private:
	void FreeResource();
};

//-----------------------------------------------------------------------------
// ValueList
//-----------------------------------------------------------------------------
class DLLDECLARE ValueList : public std::vector<Value> {
public:
	static const ValueList Null;
public:
	inline ValueList() {}
	inline ValueList(size_t n) : std::vector<Value>(n) {}
	inline ValueList(size_t n, const Value &value) : std::vector<Value>(n, value) {}
	inline ValueList(const Value &value) {
		reserve(1);
		push_back(value);
	}
	inline ValueList(const Value &value1, const Value &value2) {
		reserve(2);
		push_back(value1), push_back(value2);
	}
	inline ValueList(const Value &value1, const Value &value2, const Value &value3) {
		reserve(3);
		push_back(value1), push_back(value2), push_back(value3);
	}
	ValueList(const ValueList &valList);
	bool IsFlat() const;
	bool IsContain(const Value &value) const;
	bool IsContainIterator() const;
	bool CheckMatrix(size_t *pnRow, size_t *pnCol) const;
	void ExtractFlat(ValueList &valList) const;
	void Accept(Signal sig, ValueVisitor &visitor) const;
	void Append(const ValueList &valList);
	void Print(Signal sig, int indentLevel = 0) const;
	bool ToStringList(Signal sig, StringList &strList) const;
	static bool AssumeSameLength(Signal sig,
					const ValueList &valList1, const ValueList &valList2);
};

//-----------------------------------------------------------------------------
// ValuePtrList
//-----------------------------------------------------------------------------
typedef std::vector<const Value *> ValuePtrList;

//-----------------------------------------------------------------------------
// ValueMap
//-----------------------------------------------------------------------------
class DLLDECLARE ValueMap : public std::map<const Symbol *, Value, Symbol::KeyCompare_UniqNumber> {
public:
	static const ValueMap Null;
public:
	inline bool IsSet(const Symbol *pSymbol) const {
		return find(pSymbol) != const_cast<ValueMap *>(this)->end();
	}
	inline void Insert(const Symbol *pSymbol) {
		insert(value_type(pSymbol, Value::Null));
	}
	inline void Insert(const Symbol *pSymbol, const Value &value) {
		insert(value_type(pSymbol, value));
	}
};

//-----------------------------------------------------------------------------
// ValueDeque
//-----------------------------------------------------------------------------
typedef std::deque<Value> ValueDeque;

//-----------------------------------------------------------------------------
// ValueDict
//-----------------------------------------------------------------------------
class DLLDECLARE ValueDict : public std::map<Value, Value, Value::KeyCompare> {
public:
	static const ValueDict Null;
public:
	bool Store(Signal sig, const ValueList &valList, bool allowDupFlag);
	bool Store(Signal sig, const ValueDict &valDict, bool allowDupFlag);
	bool Store(Signal sig, const Value &valueIdx, const Value &value, bool allowDupFlag);
	inline static bool IsValidKey(const Value &value) {
		return value.IsNumber() || value.IsString() || value.IsSymbol();
	}
};

inline const char *GetNumberFormat() { return "%g"; }

}

#endif
