#include "stdafx.h"

#include <jenga/include/smoothie/Smoothie.h>

#include <Compiler.h>

#include "../BasicCompiler_Common/common.h"
#include "Opcode.h"

void PushReturnValue(int type){
	//関数の戻り値をスタックへプッシュする
	//※この処理内では、esi、ediは使用不可

	if(type==DEF_OBJECT || type==DEF_STRUCT){
		//push eax
		compiler.codeGenerator.op_push(REG_EAX);
	}
	else if(type==DEF_DOUBLE){
		//sub esp,8
		compiler.codeGenerator.op_sub_esp(8);

		//fstp qword ptr[esp]
		compiler.codeGenerator.op_fstp_basereg( DEF_DOUBLE, REG_ESP );
	}
	else if(type==DEF_SINGLE){
		//sub esp,4
		compiler.codeGenerator.op_sub_esp(4);

		//fstp dword ptr[esp]
		compiler.codeGenerator.op_fstp_basereg( DEF_SINGLE, REG_ESP );
	}
	else if(type==DEF_INT64||type==DEF_QWORD){
		//push edx
		compiler.codeGenerator.op_push(REG_EDX);

		//push eax
		compiler.codeGenerator.op_push(REG_EAX);
	}
	else if(type==DEF_LONG){
		//push eax
		compiler.codeGenerator.op_push(REG_EAX);
	}
	else if(type==DEF_INTEGER || (Smoothie::IsUnicode()&&type==DEF_CHAR)){
		//movsx ebx,ax
		compiler.codeGenerator.op_movsx_R32R16( REG_EBX, REG_EAX );

		//push ebx
		compiler.codeGenerator.op_push(REG_EBX);
	}
	else if(type==DEF_SBYTE || (Smoothie::IsUnicode()==false&&type==DEF_CHAR)){
		//movsx ebx,al
		compiler.codeGenerator.op_movsx_R32R8( REG_EBX, REG_EAX );

		//push ebx
		compiler.codeGenerator.op_push(REG_EBX);
	}
	else if(type==DEF_DWORD||type==DEF_WORD||type==DEF_BYTE||type==DEF_BOOLEAN||
		IsPtrType(type)){
		//push eax
		compiler.codeGenerator.op_push(REG_EAX);
	}
	else{
		SetError();
	}
}

void NewStringObject( const char *str ){
	///////////////////////////////////////////////////////
	// lpszTextを元にStringオブジェクトを生成し、
	// オブジェクトポインタをregに格納する
	///////////////////////////////////////////////////////

	char *parameter = (char *)malloc( lstrlen( str ) + 32 );
	sprintf( parameter, "%s%c%c*Char", str, 1, ESC_AS );

	Operator_New( *compiler.GetObjectModule().meta.GetClasses().GetStringClassPtr(), "", parameter, Type( DEF_OBJECT, *compiler.GetObjectModule().meta.GetClasses().GetStringClassPtr() ) );

	free( parameter );
}

void ExtendRegToBigType( int reg, int bigBasicType, int baseBasicType ){
	if( reg != REG_EAX ){
		SetError();
	}
	switch( Type::GetBasicSize( bigBasicType ) ){
		case sizeof(_int64):
			ExtendTypeTo64(baseBasicType);
			break;
		case sizeof(long):
			ExtendTypeTo32(baseBasicType,reg);
			break;
		case sizeof(short):
			ExtendTypeTo16(baseBasicType,reg);
			break;
	}
}



bool VarToReg( RELATIVE_VAR &relativeVar, const Type &baseType, Type &resultType ){
	const int useReg = REG_EAX;

	//大きな型への暗黙の変換
	int bigType = AutoBigCast(baseType.GetBasicType(),resultType.GetBasicType());

	if(resultType.GetBasicType()&FLAG_PTR){
		//配列ポインタ
		resultType.SetBasicType( GetPtrType(resultType.GetBasicType()^FLAG_PTR) );

		SetVarPtrToReg(useReg, &relativeVar);
	}
	else if( resultType.IsStruct() ){
		//構造体ポインタをeaxへ格納（構造体は値型）
		SetVarPtrToReg(useReg, &relativeVar);
	}
	else if( resultType.IsReal() ){
		// 実数
		SetReg_RealVariable( resultType.GetBasicType(), &relativeVar );
	}
	else if( resultType.IsWhole() || resultType.IsObject()){
		//整数型
		SetReg_WholeVariable(resultType,&relativeVar,useReg);
	}
	else if( resultType.IsStruct() ){
		//構造体ポインタをUseRegへ格納（構造体は値型）
		SetVarPtrToReg(useReg,&relativeVar);
	}
	else{
		return false;
	}

	if( resultType.GetBasicType() != bigType ){
		// 大きな型へ変換された場合
		// ※レジスタの値をキャストする
		ExtendRegToBigType( useReg, bigType, resultType.GetBasicType() );

		resultType.SetBasicType( bigType );
	}

	return true;
}
bool TermMemberOpe( const Type &leftType, const Type &baseType, Type &resultType, const char *termFull, const char *termLeft, const char *member, bool &isVariable, RELATIVE_VAR &relativeVar )
{
	const CClass &objClass = leftType.GetClass();

	const int useReg = REG_EAX;


	////////////////////////////////
	// インデクサ（getアクセサ）
	////////////////////////////////
	char VarName[VN_SIZE],ArrayElements[VN_SIZE];
	GetArrayElement(member,VarName,ArrayElements);
	if(ArrayElements[0]){
		Type classType;
		if( VarName[0] == '\0' )
		{
			classType = leftType;

			if( classType.IsObject() )
			{
				// 既にuseRegにオブジェクトポインタが格納されており、それに対するインデクサを呼び出す場合
				// ※「プロパティ値として返ってきたオブジェクトインスタンスのインデクサを呼び出す」場合にここにくる

				//オブジェクトポインタをスタックに入れておく
				//push useReg
				compiler.codeGenerator.op_push( useReg );
			}
		}
		else
		{
			GetMemberType( leftType, VarName, classType, 0, false );

			if( classType.IsObject() )
			{
				// クラス型のメンバに対するインデクサを呼び出す場合

				//オブジェクトポインタをecxにコピー
				compiler.codeGenerator.op_mov_RR( REG_ECX, useReg );

				RELATIVE_VAR tempRelativeVar;
				tempRelativeVar.dwKind=VAR_DIRECTMEM;

				if( !_member_offset(
					true,	//エラー表示あり
					false,	//読み込み専用
					leftType,
					VarName,&tempRelativeVar,classType,0)){
						return false;
				}

				// オブジェクトメンバのポインタをeaxにコピー
				if( !VarToReg( tempRelativeVar, baseType, resultType ) ){
					SetError(11,termFull,cp);
				}


				//オブジェクトポインタをスタックに入れておく
				//push eax
				compiler.codeGenerator.op_push( REG_EAX );
			}
		}

		if( classType.IsObject() )
		{
			char objectFullName[VN_SIZE], dummyArrayElements[VN_SIZE];
			GetArrayElement(termFull,objectFullName,dummyArrayElements);

			CallIndexerGetterProc(/*UseReg,*/classType,objectFullName, ArrayElements,resultType, PROCFLAG_NEW );

			compiler.codeGenerator.op_pop();

			return true;
		}
	}


	///////////////////////////////////////////////////////////////////
	// メンバを検索
	///////////////////////////////////////////////////////////////////
	if( GetMemberType( leftType, member, resultType, 0, false ) ){
		// メンバが見つかったとき

		//オブジェクトポインタをecxにコピー
		compiler.codeGenerator.op_mov_RR( REG_ECX, useReg );

		relativeVar.dwKind=VAR_DIRECTMEM;

		if( !_member_offset(
			true,	//エラー表示あり
			false,	//読み込み専用
			leftType,
			member,&relativeVar,resultType,0)){
				return false;
		}

		// 変数として扱う
		isVariable = true;

		return true;
	}


	///////////////////////////////////////////////////////////////////
	// 動的メソッドを検索
	///////////////////////////////////////////////////////////////////
	vector<const UserProc *> userProcs;

	char methodName[VN_SIZE], lpPtrOffset[VN_SIZE], parameter[VN_SIZE], dummy[1];
	ReferenceKind refType;
	bool isParameterInBracket = false;
	lstrcpy( methodName, member );
	GetVarFormatString( methodName, parameter, lpPtrOffset, dummy, refType, &isParameterInBracket );

	objClass.EnumDynamicMethodsOrInterfaceMethods( methodName, userProcs );
	if(userProcs.size()){
		//オーバーロードを解決
		const UserProc *pUserProc = OverloadSolutionWithStrParam(termFull,userProcs,parameter,termLeft);

		if( pUserProc )
		{
			if(
				pUserProc->Params().size() == 0				// 仮引数の個数は0
				&& parameter[0]								// 実引数は1つ以上
				&& pUserProc->ReturnType().IsObject()		// 戻り値がクラス型の場合
				&& isParameterInBracket )					// 実引数は[]で囲まれている
			{
				// プロパティ値として返ってきたオブジェクトインスタンスのインデクサを呼び出す

				// まずはプロパティ値を取得
				bool dummyIsVariable;
				RELATIVE_VAR dummyRelativeVar;
				TermMemberOpe( leftType, baseType, resultType, termFull, termLeft, methodName, dummyIsVariable, dummyRelativeVar );

				// 戻り値のオブジェクトインスタンスのインデクサを呼び出す
				char temporary[VN_SIZE], temp2[VN_SIZE];
				sprintf( temporary, "[%s]", parameter );
				sprintf( temp2, "%s.%s", termLeft, methodName );
				Type classType = resultType;
				return TermMemberOpe( classType, baseType, resultType, termFull, temp2, temporary, isVariable, relativeVar );
			}

			resultType = pUserProc->ReturnType();

			{
				//オブジェクトポインタをスタックに入れておく
				//push reg
				compiler.codeGenerator.op_push( useReg );

				if( !Opcode_CallProc(parameter,pUserProc,PROCFLAG_NEW,termLeft) ){

					return false;
				}

				compiler.codeGenerator.op_pop();

				/////////////////////
				// 戻り値の処理
				/////////////////////

				//大きな型への暗黙の変換
				int bigType = AutoBigCast(baseType.GetBasicType(), resultType.GetBasicType() );

				if( resultType.GetBasicType() != bigType ){
					// 大きな型へ変換された場合
					// ※レジスタの値をキャストする
					ExtendRegToBigType( REG_EAX, bigType, resultType.GetBasicType() );

					resultType.SetBasicType( bigType );
				}

				//SetUseRegFromRax(resultType.GetBasicType(),UseReg,XmmReg);

				// 型パラメータを解決
				ResolveFormalGenericTypeParameter( resultType, leftType, pUserProc );
			}
			
			return true;
		}
	}

	SetError();

	return false;
}
bool _TermOpe( const char *term, const Type &baseType, Type &resultType, bool &isLiteral, BOOL *pbUseHeap, bool *pIsClassName, bool isProcedureCallOnly, bool &isVariable, RELATIVE_VAR &relativeVar, bool isWriteAccess )
{
	char parameter[VN_SIZE];

	// Withを解決
	char termFull[VN_SIZE];
	if(term[0]=='.'){
		GetWithName(termFull);
		lstrcat(termFull,term);
	}
	else lstrcpy(termFull,term);

	char termLeft[VN_SIZE];
	lstrcpy(termLeft,termFull);

	// パース
	char member[VN_SIZE];
	ReferenceKind refType;
	if( SplitMemberName( termFull, termLeft, member, refType ) ){
		///////////////////////////////////////////////////////////////////
		// オブジェクトとメンバに分解できるとき
		// termLeft.member
		///////////////////////////////////////////////////////////////////

		isLiteral = false;

		// オブジェクト側の型を取得
		bool isClassName = false;
		Type leftType;
		if( GetTermType( termLeft, Type(), leftType, isLiteral, &isClassName ) ){
			if( isClassName == false && compiler.GetObjectModule().meta.GetBlittableTypes().IsExist( leftType ) ){
				// 左側のオブジェクト部分がBlittable型のとき

				char temporary[VN_SIZE];
				lstrcpy( temporary, termLeft );
				sprintf( termLeft, "%s(%s)",
					compiler.GetObjectModule().meta.GetBlittableTypes().Find( leftType ).GetCreateStaticMethodFullName().c_str(),
					temporary );
			}
		}

		if( !TermOpe( termLeft, baseType, leftType, isLiteral, pbUseHeap, &isClassName ) ){
			goto globalArea;
		}

		if( isClassName ){
			// 静的メンバ/メソッドの場合
			goto globalArea;
		}

		if( !leftType.HasMember() ){
			// メンバを持たない型の場合
			if( isProcedureCallOnly )
			{
				SetError(1,NULL,cp);
			}
			return false;
		}

		return TermMemberOpe( leftType, baseType, resultType, termFull, termLeft, member, isVariable, relativeVar );
	}
globalArea:


	//////////////////////////////////////////////
	// クラス名かどうかをチェック（静的メンバ用）
	//////////////////////////////////////////////

	if( pIsClassName ){
		if( compiler.GetObjectModule().meta.GetClasses().Find( termFull ) ){
			*pIsClassName = true;
			return true;
		}
	}


	/////////////////////////////////////////////////////////////////
	// グローバル属性エリア
	/////////////////////////////////////////////////////////////////

	const int useReg = REG_EAX;


	if(lstrcmpi(termFull,"This")==0 && isProcedureCallOnly == false ){
		if( compiler.pCompilingClass == NULL )
		{
			SetError(142,NULL,cp);
			return false;
		}

		//Thisオブジェクト
		resultType.SetType( DEF_OBJECT, compiler.pCompilingClass );

		SetThisPtrToReg( useReg );

		isLiteral = false;

		return true;
	}


	//////////////////////////////////////
	// 関数（DLL、ユーザー定義、組み込み）
	//////////////////////////////////////
	char procName[VN_SIZE];
	char temporary[8192];

	int i2=GetCallProcName(termFull,procName);
	if(termFull[i2]=='('){
		int i4=GetStringInPare_RemovePare(parameter,termFull+i2+1);

		void *pInfo;
		int idProc=GetProc(procName,(void **)&pInfo);

		if(idProc)
		{
			if(termFull[i2+1+i4+1]!='\0')
			{
				//閉じカッコ")"に続く文字がNULLでないとき
				SetError(42,NULL,cp);
			}


			{
				////////////////
				// 呼び出し
				////////////////

				CallProc(idProc,pInfo,procName,parameter, baseType,resultType);


				/////////////////////
				// 戻り値の処理
				/////////////////////

				//大きな型への暗黙の変換
				int bigType = AutoBigCast(baseType.GetBasicType(), resultType.GetBasicType() );

				/*
				※後でNumOpe内でプッシュする
				//スタックへプッシュ
				PushReturnValue( resultType.GetBasicType() );
				*/

				if( resultType.GetBasicType() != bigType ){
					// 大きな型へ変換された場合
					// ※レジスタの値をキャストする
					ExtendRegToBigType( useReg, bigType, resultType.GetBasicType() );

					resultType.SetBasicType( bigType );
				}

				//SetUseRegFromRax(resultType.GetBasicType(),UseReg,XmmReg);
			}


			if(resultType.IsStruct()){
				//構造体が戻ったときはヒープ領域にインスタンスが格納されている
				//※後にfreeする必要あり
				// TODO: 解放はGCに任せる
				*pbUseHeap = 1;
			}

			isLiteral = false;

			return true;
		}

		ConstMacro *pConstMacro = compiler.GetObjectModule().meta.GetGlobalConstMacros().Find( procName );
		if( pConstMacro )
		{
			if( pConstMacro->GetCalcBuffer( parameter, temporary ) )
			{
				/////////////////////////
				// マクロ関数
				/////////////////////////

				//閉じカッコ")"に続く文字がNULLでないときはエラーにする
				if(termFull[i2+1+i4+1]!='\0') SetError(42,NULL,cp);

				//マクロ関数の場合
				NumOpe(useReg, temporary,Type(),resultType);

				if(!IS_LITERAL(resultType.GetIndex())){
					//リテラル値ではなかったとき
					isLiteral = false;
				}

				return true;
			}
		}
	}
	else if( isProcedureCallOnly ){
		// 関数呼び出し以外は受け付けない
		return false;
	}


	////////////////////////////////
	// インデクサ（getアクセサ）
	////////////////////////////////

	char VarName[VN_SIZE],ArrayElements[VN_SIZE];
	GetArrayElement(termFull,VarName,ArrayElements);
	if(ArrayElements[0]){
		Type classType;
		GetVarType(VarName,classType,false);
		if( classType.IsObject() )
		{
			CallIndexerGetterProc(/*UseReg,*/classType,VarName, ArrayElements,resultType);

			isLiteral = false;

			return true;
		}
	}


	////////////////////////////////
	// 変数
	////////////////////////////////

	if(GetVarOffset(
		false,	//エラー表示なし
		isWriteAccess,
		termFull,
		&relativeVar,resultType)){
		//////////
		// 変数
		//////////

		// 変数として扱う
		isVariable = true;

		isLiteral = false;

		return true;
	}


	/////////////////////////////////
	// プロパティ用のメソッド
	/////////////////////////////////

	//配列要素を排除
	GetArrayElement(termFull,VarName,ArrayElements);

	if(GetSubHash(VarName,0)){

		{
			CallPropertyMethod(termFull,NULL,resultType);

			//大きな型への暗黙の変換
			int bigType = AutoBigCast(baseType.GetBasicType(), resultType.GetBasicType() );

			if( resultType.GetBasicType() != bigType ){
				// 大きな型へ変換された場合
				// ※レジスタの値をキャストする
				ExtendRegToBigType( REG_EAX, bigType, resultType.GetBasicType() );

				resultType.SetBasicType( bigType );
			}

			//SetUseRegFromRax(resultType.GetBasicType(),UseReg,XmmReg);
		}


		if(resultType.IsStruct()){
			//構造体が戻ったときはヒープ領域にインスタンスが格納されている
			//※後にfreeする必要あり
			// TODO: 解放はGCに任せる
			*pbUseHeap = 1;
		}

		isLiteral = false;

		return true;
	}

	if( isProcedureCallOnly )
	{
		SetError(3, termLeft, cp );
	}

	return false;
}

bool TermOpe( const char *term, const Type &baseType, Type &resultType, bool &isLiteral, BOOL *pbUseHeap, bool *pIsClassName, bool isProcedureCallOnly, bool isWriteAccess )
{
	RELATIVE_VAR relativeVar;
	bool isVariable = false;
	bool result = _TermOpe( term, baseType, resultType, isLiteral, pbUseHeap, pIsClassName, isProcedureCallOnly, isVariable, relativeVar, isWriteAccess );

	if( isVariable )
	{
		// 変数の場合はeaxに変数ポインタを格納する
		if( !VarToReg( relativeVar, baseType, resultType ) ){
			SetError(11,term,cp);
		}
	}

	return result;
}
bool TermOpeOnlyVariable( const char *term, Type &resultType, RELATIVE_VAR &relativeVar, bool isWriteAccess )
{
	bool isLiteral, isVariable = false;
	bool result = _TermOpe( term, Type(), resultType, isLiteral, NULL, NULL, false, isVariable, relativeVar, isWriteAccess );

	if( !isVariable )
	{
		SetError();
	}

	return result;
}


bool NumOpe( int reg,
			const char *expression,
			const Type &baseType,
			Type &resultType,
			BOOL *pbUseHeap ){

	if( !NumOpe( expression, baseType, resultType, pbUseHeap ) ){
		return false;
	}

	if( reg != REG_EAX ){
		// TODO: 未実装
		SetError();
	}

	if( resultType.IsReal() ){
		//fld ptr[esp]
		compiler.codeGenerator.op_fld_ptr_esp( resultType.GetBasicType() );

		//add esp,size
		compiler.codeGenerator.op_add_esp( resultType.GetBasicSize() );
	}
	else{
		//pop eax
		compiler.codeGenerator.op_pop(REG_EAX);

		if( resultType.Is64() ){
			//pop edx
			compiler.codeGenerator.op_pop(REG_EDX);
		}
	}
	return true;
}
bool NumOpe( const char *expression,
			const Type &baseType,
			Type &resultType,
			BOOL *pbUseHeap )
{
	int i,i2,i3;
	char temporary[1024],temp2[1024];

	if(expression[0]=='\0'){
		SetError(1,NULL,cp);
		return false;
	}

	if( !baseType.IsNull() && expression[0] == '[' ){
		// リテラル配列の場合

		int dataTableOffset;
		if( !compiler.GetObjectModule().dataTable.MakeLiteralArrayBuffer( expression, baseType, dataTableOffset ) )
		{
			return false;
		}

		//mov eax,i2
		compiler.codeGenerator.op_mov_RV(REG_EAX,dataTableOffset, Schedule::DataTable );

		resultType = baseType;

		//push eax
		compiler.codeGenerator.op_push( REG_EAX );

		return true;
	}

	bool isLiteralCalculation;
	if( NumOpe_GetType( expression, baseType, resultType, &isLiteralCalculation ) )
	{
		if( isLiteralCalculation )
		{
			//右辺値が数値の定数式の場合
			_int64 i64data;
			StaticCalculation(true, expression,baseType.GetBasicType(),&i64data,resultType);

			if( resultType.GetBasicSize() == sizeof(_int64) ){
				//64ビット（符号有り整数/実数）

				//push HILONG(i64data)
				compiler.codeGenerator.op_push_V((long)*(long *)(((char *)(&i64data))+4));

				//push LOLONG(i64data)
				compiler.codeGenerator.op_push_V(*(long *)(&i64data));
			}
			else if( resultType.IsSingle() ){
				//single実数

				double dbl;
				memcpy(&dbl,&i64data,sizeof(_int64));

				float flt;
				flt=(float)dbl;
				long l;
				memcpy(&l,&flt,sizeof(long));

				//push flt
				compiler.codeGenerator.op_push_V(l);
			}
			else{
				//整数（符号有り/無し）

				long l = (long)i64data;

				if(resultType.GetBasicSize()==sizeof(char)) l = l & 0x000000FF;
				if(resultType.GetBasicSize()==sizeof(short)) l = l & 0x0000FFFF;

				//push term
				compiler.codeGenerator.op_push_V(l);
			}
			return true;
		}
	}

	if(expression[0]==1 )
	{
		if( expression[1]==ESC_NEW ){
			//New演算子（オブジェクト生成）

			if( !Operator_New( expression+2, baseType, resultType ) ){
				return false;
			}

			return true;
		}
		else if( expression[1] == ESC_SYSTEM_STATIC_NEW )
		{
			// 静的領域にオブジェクトを作る

			// 静的領域にオブジェクトを生成
			int dataTableOffset;
			if( !compiler.GetObjectModule().dataTable.MakeConstObjectToProcessStaticBuffer( expression + 2, resultType, dataTableOffset ) )
			{
				return false;
			}

			// push value
			compiler.codeGenerator.op_push_V( dataTableOffset, Schedule::DataTable );

			return true;
		}
	}


	/////////////////////////////////
	// 式要素を逆ポーランド式で取得
	/////////////////////////////////

	char *values[255];
	long calc[255];
	long stack[255];
	int pnum;
	if(!GetNumOpeElements(expression,&pnum,values,calc,stack)){
		for(i=0;i<pnum;i++){
			if(values[i]) HeapDefaultFree(values[i]);
		}
		return false;
	}


	BOOL bError;
	bError=0;

	//リテラル値のみの計算かどうかを判別するためのフラグ
	BOOL bLiteralCalculation=1;

	double dbl;
	int sp;
	int type_stack[255];
	bool isNothing_stack[255];
	LONG_PTR index_stack[255];
	BOOL bUseHeap[255];
	_int64 i64data;
	for(i=0,sp=0;i<pnum;i++){
		int idCalc;
		idCalc=calc[i]%100;

		if(idCalc){
			if(type_stack[sp-2]==DEF_OBJECT){
				if( idCalc == CALC_AS
					&& type_stack[sp-1] == ( DEF_OBJECT | FLAG_CAST )
					&& index_stack[sp-1] == index_stack[sp-2]
					|| isNothing_stack[sp-2] ){
						// 同一の型、またはNothingに対するAsはAs演算子を呼び出さない
				}
				else if( idCalc == CALC_AS
					&& type_stack[sp-1] == ( DEF_OBJECT | FLAG_CAST )
					&& ( ((CClass *)index_stack[sp-1])->IsEqualsOrSubClass( (CClass *)index_stack[sp-2] ) || ((CClass *)index_stack[sp-2])->IsEqualsOrSubClass( (CClass *)index_stack[sp-1] )
					)){
						// ダウンキャストを許可する
				}
				else{
					//オーバーロードされたオペレータを呼び出す
					i2=CallOperatorProc(idCalc,baseType,type_stack,index_stack,bUseHeap,sp);
					if(i2==0){
						if(idCalc==CALC_EQUAL) lstrcpy(temp2,"==");
						else GetCalcName(idCalc,temp2);
						sprintf(temporary,"Operator %s",temp2);
						SetError(27,temporary,cp);
						goto error;
					}
					else if(i2==-1) goto error;

					continue;
				}
			}

			if(!CheckCalcType(idCalc,type_stack,sp)) goto error;
		}

		switch(idCalc){
			//数値
			case 0:
				index_stack[sp]=-1;
				isNothing_stack[sp] = false;
				bUseHeap[sp]=0;

				char *term;
				term=values[i];

				if( calc[i+1]%100 == CALC_AS ){
					// As演算子の右辺値
					//型名
					if( compiler.StringToType( term, resultType ) ){
						resultType.SetBasicType( resultType.GetBasicType() | FLAG_CAST );
					}
					else{
						SetError(3, term, cp );
						goto error;
					}

					type_stack[sp] = resultType.GetBasicType();
					index_stack[sp] = resultType.GetIndex();
					sp++;

					break;
				}

				if( (term[0]=='e'||term[0]=='E')
					&& (term[1]=='x'||term[1]=='X')
					&& term[2]=='\"'
					|| term[0] == '\"' )
				{
					bool isEx = true;
					if( term[0] == '\"' )
					{
						isEx = false;
					}

					if( isEx )
					{
						// 拡張版リテラル文字列（エスケープシーケンス可能）
						if(!RemoveStringQuotes(term+2)){
							SetError(43,NULL,cp);
							goto error;
						}
						i3=FormatString_EscapeSequence(term+2);
						term+=2;
					}
					else
					{
						// 通常文字列
						if(!RemoveStringQuotes(term)){
							SetError(43,NULL,cp);
							goto error;
						}
						i3=lstrlen(term);
					}

					if( !baseType.IsPointer() )
					{
						//要求タイプがオブジェクト、または未定のとき

						//String型オブジェクトを生成
						i2 = compiler.GetObjectModule().dataTable.MakeConstStringObjectToProcessStaticBuffer( term );
						
						// push value
						compiler.codeGenerator.op_push_V( i2, Schedule::DataTable );

						type_stack[sp]=DEF_OBJECT;
						index_stack[sp]=(LONG_PTR)compiler.GetObjectModule().meta.GetClasses().GetStringClassPtr();
						bLiteralCalculation=0;

						sp++;
						break;
					}
StrLiteral:
					type_stack[sp]=typeOfPtrChar;
					bLiteralCalculation=0;

					i2=compiler.GetObjectModule().dataTable.AddString(term,i3);

					//push DataSize
					compiler.codeGenerator.op_push_V( i2, Schedule::DataTable );
				}
				else if(IsVariableTopChar(term[0])||
					term[0]=='*'||
					(term[0]=='.'&&IsVariableTopChar(term[1]))){
					//////////////////
					// 何らかの識別子

					bool isLiteral;
					if( TermOpe( term, baseType, resultType, isLiteral, &bUseHeap[sp] ) ){
						if(resultType.IsNull()){
							//戻り値が存在しないとき
							for(i2=0;;i2++){
								if(term[i2]=='('||term[i2]=='\0'){
									term[i2]=0;
									break;
								}
							}
							SetError(38,term,cp);

							goto error;
						}

						type_stack[sp] = resultType.GetBasicType();
						index_stack[sp] = resultType.GetIndex();

						if( !isLiteral ){
							bLiteralCalculation=0;
						}

						if( resultType.GetBasicType() & FLAG_CAST ){
							// 型名のみ
							SetError();
						}
						else{
							if( resultType.IsReal() ){
								//sub esp,size
								//fstp ptr[esp]
								compiler.codeGenerator.op_fstp_push( resultType );
							}
							else{
								if( resultType.Is64() ){
									//push edx
									compiler.codeGenerator.op_push( REG_EDX );
								}
								else{
									ExtendTypeTo32( resultType.GetBasicType(), REG_EAX );
								}

								//push eax
								compiler.codeGenerator.op_push( REG_EAX );
							}
						}

						sp++;
						break;
					}


					// Nothing
					if( lstrcmp( term, "Nothing" ) == 0 ){
						isNothing_stack[sp] = true;

						type_stack[sp] = DEF_OBJECT;
						if( baseType.IsObject() ){
							index_stack[sp] = baseType.GetIndex();
						}
						else{
							index_stack[sp] = (LONG_PTR)compiler.GetObjectModule().meta.GetClasses().GetObjectClassPtr();
						}

						bLiteralCalculation = 0;

						//push 0
						compiler.codeGenerator.op_push_V( 0 );

						sp++;
						break;
					}


					//////////////
					// 定数の場合
					//////////////

					i3 = compiler.GetObjectModule().meta.GetGlobalConsts().GetBasicType(term);
					if(i3){
						if( compiler.GetObjectModule().meta.GetGlobalConsts().IsStringPtr( term ) ){
							//リテラル文字列

							if( baseType.IsObject() || baseType.IsNull() )
							{
								//要求タイプがオブジェクト、または未定のとき

								//String型オブジェクトを生成
								NewStringObject(term);

								type_stack[sp]=DEF_OBJECT;
								index_stack[sp]=(LONG_PTR)compiler.GetObjectModule().meta.GetClasses().GetStringClassPtr();
								bLiteralCalculation=0;

								sp++;
								break;
							}

							double dbl = compiler.GetObjectModule().meta.GetGlobalConsts().GetDoubleData(term);
							memcpy(&i64data,&dbl,sizeof(double));

							//バイト数
							i3=lstrlen((char *)i64data);

							memcpy(term,(char *)i64data,i3);
							term[i3]=0;
							goto StrLiteral;
						}

						type_stack[sp]=i3;
						if(IsRealNumberType(i3)){
							//実数
							double dbl = compiler.GetObjectModule().meta.GetGlobalConsts().GetDoubleData(term);
							memcpy(&i64data,&dbl,sizeof(double));
							goto Literal;
						}
						else if(IsWholeNumberType(i3)){
							//整数
							i64data = compiler.GetObjectModule().meta.GetGlobalConsts().GetWholeData(term);
							goto Literal;
						}
						else{
							SetError(300,NULL,cp);
							goto error;
						}
					}


					//該当する識別子が見当たらないときはエラー扱いにする
					bError=1;
					SetError(3,term,cp);
					type_stack[sp]=DEF_DOUBLE;
				}
				else{
					//リテラル値
					type_stack[sp]=GetLiteralValue(term,&i64data,baseType.GetBasicType());
Literal:
					if(type_stack[sp]==DEF_INT64||
						type_stack[sp]==DEF_QWORD||
						type_stack[sp]==DEF_DOUBLE){
						//64ビット（符号有り整数/実数）

						//push HILONG(dbl)
						compiler.codeGenerator.op_push_V((long)*(long *)(((char *)(&i64data))+4));

						//push LOLONG(dbl)
						compiler.codeGenerator.op_push_V(*(long *)(&i64data));
					}
					else if(type_stack[sp]==DEF_SINGLE){
						//single実数

						float flt;
						memcpy(&dbl,&i64data,sizeof(double));
						flt=(float)dbl;
						memcpy(&i3,&flt,sizeof(long));

						//push term
						compiler.codeGenerator.op_push_V(i3);
					}
					else{
						//その他

						//push term
						compiler.codeGenerator.op_push_V((long)i64data);

						if((long)i64data==0) index_stack[sp]=LITERAL_NULL;
					}


					//リテラル値の種類
					if(Is64Type(type_stack[sp])==0&&IsRealNumberType(type_stack[sp])==0){
						//整数（符号有り/無し）

						index_stack[sp]=GetLiteralIndex(i64data);
					}
				}
				sp++;
				break;

			//論理演算子
			case CALC_XOR:
				//value[sp-2] xor= value[sp-1]
				//xor演算
				if(!Calc_Xor(type_stack,index_stack,&sp)) goto error;
				break;
			case CALC_OR:
				//value[sp-2] or= value[sp-1]
				//or演算
				if(!Calc_Or(type_stack,index_stack,&sp)) goto error;
				break;
			case CALC_AND:
				//value[sp-2] and= value[sp-1]
				//and演算
				if(!Calc_And(type_stack,index_stack,&sp)) goto error;
				break;
			case CALC_NOT:
				//value[sp-1]=Not value[sp-1]
				//NOT演算子
				if(!Calc_Not(type_stack,sp)) goto error;
				break;

			//比較演算子
			case CALC_PE:
				//value[sp-2]<=value[sp-1]
				if(!Calc_Relation_PE(type_stack,index_stack,&sp)) goto error;
				break;
			case CALC_QE:
				//value[sp-2]>=value[sp-1]
				if(!Calc_Relation_QE(type_stack,index_stack,&sp)) goto error;
				break;
			case CALC_P:
				//value[sp-2]<value[sp-1]
				if(!Calc_Relation_P(type_stack,index_stack,&sp)) goto error;
				break;
			case CALC_Q:
				//value[sp-2]>value[sp-1]
				if(!Calc_Relation_Q(type_stack,index_stack,&sp)) goto error;
				break;
			case CALC_NOTEQUAL:
				//value[sp-2]<>value[sp-1]
				if(!Calc_Relation_NotEqual(type_stack,&sp)) goto error;
				break;
			case CALC_EQUAL:
				//value[sp-2]=value[sp-1]
				if(!Calc_Relation_Equal(type_stack,&sp)) goto error;
				break;

			//ビットシフト
			case CALC_SHL:
				//value[sp-2]=value[sp-2]<<value[sp-1]
				if(!Calc_SHL(type_stack,&sp)) goto error;
				break;
			case CALC_SHR:
				//value[sp-2]=value[sp-2]>>value[sp-1]
				if(!Calc_SHR(type_stack,&sp)) goto error;
				break;

			//算術演算
			case CALC_ADDITION:
			case CALC_SUBTRACTION:
			case CALC_PRODUCT:
				if(!CalcTwoTerm_Arithmetic(idCalc,type_stack,index_stack,&sp)) goto error;
				break;

			case CALC_MOD:
				//value[sp-2]%=value[sp-1]
				//剰余演算
				if(!Calc_Mod(type_stack,&sp)) goto error;
				break;
			case CALC_QUOTIENT:
				//value[sp-2]/=value[sp-1];
				//除算
				if(!Calc_Divide(type_stack,&sp,baseType.GetBasicType())) goto error;
				break;
			case CALC_INTQUOTIENT:
				//value[sp-2]/=value[sp-1]
				//整数除算
				if(!Calc_IntDivide(type_stack,index_stack,&sp)) goto error;
				break;
			case CALC_MINUSMARK:
				//value[sp-1]=-value[sp-1]
				//符号反転
				if(!Calc_MinusMark(type_stack,sp)) goto error;
				index_stack[sp-1]=-1;
				break;
			case CALC_POWER:
				//べき乗演算（浮動小数点演算のみ）
				if(!Calc_Power(type_stack,&sp)) goto error;
				break;
			case CALC_AS:
				//キャスト
				if(!Calc_Cast(type_stack,index_stack,&sp)) goto error;
				break;

			case CALC_BYVAL:
				//ポインタ型→参照型
				if( PTR_LEVEL( type_stack[sp-1] ) <= 0 ){
					//ポインタ型ではないとき
					SetError( 3, NULL, cp );
					goto error;
				}

				type_stack[sp-1] = PTR_LEVEL_DOWN( type_stack[sp-1] );

				break;

			default:
				SetError(300,NULL,cp);
				goto error;
		}
	}

	if(bError) goto error;

	if(sp!=1){
		SetError(1,NULL,cp);
		goto error;
	}

	if(bLiteralCalculation){
		//右辺値が数値の定数式の場合
		SetError();
	}
	else{
		//右辺値が数値の定数式ではないとき
		if(IS_LITERAL(index_stack[0])) index_stack[0]=-1;
	}

	if(pbUseHeap) *pbUseHeap=bUseHeap[0];

	resultType.SetType( type_stack[0], index_stack[0] );

	bool isSuccessful = true;
	goto finish;


error:
	isSuccessful = false;
	goto finish;


finish:

	for(i=0;i<pnum;i++){
		if(values[i]) HeapDefaultFree(values[i]);
	}

	// 強制終了を防ぐためのダミー（原因不明）
	if( lstrcmp( expression, "-1/t" ) == 0 )
	{
	}

	return isSuccessful;
}
