#ifndef __COMMON_H__
#define __COMMON_H__

#if defined(__BORLANDC__) || defined(_MSC_VER)
#include <windows.h>	// WINVER is defined
#endif
#include <stdio.h>
#include <stdarg.h>
#include <tchar.h>
#include <math.h>

#include <complex>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <memory>
#include <algorithm>

extern "C" {
#include "SFMT.h"
}

#define NUMBEROF(x) (sizeof(x) / sizeof(x[0]))
#define foreach(T, i, c) for (T::iterator i = (c).begin(); i != (c).end(); i++)
#define foreach_const(T, i, c) for (T::const_iterator i = (c).begin(); i != (c).end(); i++)
#define foreach_reverse(T, i, c) for (T::reverse_iterator i = (c).rbegin(); i != (c).rend(); i++)
#define foreach_const_reverse(T, i, c) for (T::const_reverse_iterator i = (c).rbegin(); i != (c).rend(); i++)

#ifdef DEBUG_ASCRIPT
#define DBG(x) x
#define DBGPARSER(x) x
#define ASSUME(env, x) if (!(x)) { env.Error(__FILE__, __LINE__, #x); }
#else
#define DBG(x)
#define DBGPARSER(x)
#define ASSUME(env, x) if (!(x)) { env.Error(__FILE__, __LINE__, #x); }
#endif

#define ERROREND(env, str) (env).Error(__FILE__, __LINE__, (str));

#define AScript_Symbol(name) (SymbolPool::GetInstance()->_pSymbol_##name)

#define AScript_DeclareSymbol(name) \
const Symbol *_pSymbol_##name

#define AScript_RealizeSymbol(name) \
_pSymbol_##name = Symbol::Add(#name);

#define AScript_RealizeSymbolEx(name, str) \
_pSymbol_##name = Symbol::Add(str);

typedef _TCHAR TCHAR;

namespace AScript {

extern const int MAX_STACK_LEVEL;

//-----------------------------------------------------------------------------
// Simple type declarations
//-----------------------------------------------------------------------------
class Symbol;
class SymbolSet;
class Value;
class ValueList;
class ValueMap;
class Function;
class Environment;

typedef double Number;
typedef std::complex<Number> Complex;
typedef std::basic_string<TCHAR> String;

enum ErrorType {
	ERR_None,
	ERR_SyntaxError,
	ERR_ArithmeticError,
	ERR_TypeError,
	ERR_ZeroDivisionError,
	ERR_ValueError,
	ERR_SystemError,
	ERR_IOError,
	ERR_IndexError,
	ERR_KeyError,
	ERR_ImportError,
	ERR_AttributeError,
};

enum FunctionType {
	FUNCTYPE_Function,
	FUNCTYPE_Class,
	FUNCTYPE_Instance,
	FUNCTYPE_Block,
};

enum OccurPattern {
	OCCUR_Invalid,
	OCCUR_Zero,			// (none)
	OCCUR_Once,			// 1
	OCCUR_ZeroOrOnce,	// ?
	OCCUR_ZeroOrMore,	// *
	OCCUR_OnceOrMore,	// +
};

enum ValueType {
	// this order affects on the function of Value::Compare()
	VTYPE_Invalid,
	VTYPE_Symbol,
	VTYPE_Boolean,
	VTYPE_Number,
	VTYPE_Complex,
	VTYPE_String,
	VTYPE_Module,
	VTYPE_Class,
	VTYPE_Object,
	VTYPE_Function,		// specific type of Object
	VTYPE_List,			// specific type of Object
	VTYPE_Dict,			// specific type of Object
	VTYPE_File,			// specific type of Object
	VTYPE_FileStat,		// specific type of Object
	VTYPE_DateTime,		// specific type of Object
	VTYPE_Expr,			// specific type of Object
	VTYPE_Environment,	// specific type of Object
	VTYPE_Error,		// specific type of Object
	VTYPE_Struct,		// specific type of Object
	VTYPE_Quote,		// this type is used in declaration
	VTYPE_AnyType,		// this type is used in declaration
};

enum SignalType {
	SIGTYPE_None,
	SIGTYPE_Error,
	SIGTYPE_Break,
	SIGTYPE_Continue,
	SIGTYPE_Return,
};

enum EnvType {
	ENVTYPE_Invalid,
	ENVTYPE_Root,
	ENVTYPE_Local,
	ENVTYPE_Block,
	ENVTYPE_Module,
	ENVTYPE_Class,
	ENVTYPE_Instance,
	ENVTYPE_Method,
	ENVTYPE_Lister,
	ENVTYPE_Outer,	// this type is not set as type of each frame
};

enum ResultMode {
	RSLTMODE_Normal,
	RSLTMODE_List,	// :list
	RSLTMODE_XList,	// :xlist
	RSLTMODE_Set,	// :set
	RSLTMODE_XSet,	// :xset
	RSLTMODE_Void,	// :void
};

enum MapFlag {
	MAP_Off,
	MAP_On,
};

const Symbol *GetValueTypeSymbol(ValueType valType);
const Symbol *GetOccurPatternSymbol(OccurPattern occurPattern);
const TCHAR *GetSignalTypeName(SignalType sigType);
const TCHAR *GetEnvTypeName(EnvType envType);
const TCHAR *GetErrorTypeName(ErrorType errType);

//void InitModule(Environment &env);

//-----------------------------------------------------------------------------
// RandomNumberGenerator
//-----------------------------------------------------------------------------
class RandomNumberGenerator {
public:
	inline int operator()(int n) {
		return static_cast<int>(::genrand_real2() * n);
	}
};

}
#endif
