#include "stdafx.h" #include #include #include "../BasicCompiler_Common/common.h" #include "Opcode.h" void OpcodeOthers( const char *Command ){ int i,i2; char leftTerm[8192]; int lastParePos = 0; for(i=0;;i++){ if(Command[i]=='\"'){ //ダブルクォートは不正なのでエラー扱い leftTerm[i]=0; SetError(3,leftTerm,cp); return; } if(Command[i]=='('){ lastParePos = i; i2=GetStringInPare(leftTerm+i,Command+i); i+=i2-1; continue; } if(Command[i]=='['){ i2=GetStringInBracket(leftTerm+i,Command+i); i+=i2-1; continue; } if(Command[i]=='\0'){ leftTerm[i] = 0; break; } if( IsNumCalcMark( Command, i ) ){ leftTerm[i] = 0; break; } leftTerm[i]=Command[i]; } if(!( IsVariableTopChar(leftTerm[0])|| leftTerm[0]=='.'|| (leftTerm[0]==1&&leftTerm[1]==ESC_PSMEM) )){ SetError(1,NULL,cp); return; } if(Command[i]=='\0' && lastParePos == 0){ ////////////////////////////// // パラメータ無しのマクロ検索 ////////////////////////////// const UserProc *pUserProc = GetSubHash(Command); //GetSubHash内でエラー提示が行われた場合 if(pUserProc==(UserProc *)-1) return; if(pUserProc==0){ char temporary[VN_SIZE]; lstrcpy(temporary,Command); CharUpper(temporary); pUserProc=GetSubHash(temporary); //GetSubHash内でエラー提示が行われた場合 if(pUserProc==(UserProc *)-1) return; } if(pUserProc){ if( !pUserProc->IsMacro() ){ SetError(10,Command,cp); } Opcode_CallProc("",pUserProc,0,""); return; } } else if(IsNumCalcMark(Command,i)){ //代入演算 OpcodeCalc(Command); return; } Type resultType; bool isLiteral; BOOL bUseHeap; bool result = TermOpe( leftTerm, Type(), resultType, isLiteral, &bUseHeap, false, NULL, true ); if( result ){ ///////////////////// // 戻り値の処理 ///////////////////// if( resultType.IsReal() ){ //fstp st(0) compiler.codeGenerator.PutOld( (char)0xDD, (char)0xD8 ); } else if( resultType.IsStruct() ){ //mov ebx,eax compiler.codeGenerator.op_mov_RR(REG_EBX,REG_EAX); FreeTempObject(REG_EBX,&resultType.GetClass()); } return; } // どこにも当てはまらなかったため、失敗 SetError(1,NULL,cp); } void OpcodeIf(char *Parameter){ int i,i2; Type tempType; for(i=0;;i++){ if(Parameter[i]=='\0'){ SetError(21,NULL,cp); return; } if(Parameter[i]==1&&Parameter[i+1]==ESC_THEN){ Parameter[i]=0; break; } } const PertialSchedule *pIfPertialSchedule = NULL; if( !NumOpe(Parameter,Type(DEF_BOOLEAN),tempType) ){ //NumOpe内でエラー } else if( tempType.IsDouble() ){ //fld qword ptr[esp] compiler.codeGenerator.op_fld_ptr_esp(DEF_DOUBLE); //push 0 compiler.codeGenerator.op_push_V(0); //fild dword ptr[esp] compiler.codeGenerator.op_fld_ptr_esp(DEF_LONG); //add esp,sizeof(double)+sizeof(long) compiler.codeGenerator.op_add_esp(sizeof(double)+sizeof(long)); //fcompp compiler.codeGenerator.op_fcompp(); //fnstsw ax compiler.codeGenerator.op_fnstsw_ax(); //test ah,40 compiler.codeGenerator.op_test_ah( (char)0x40 ); //jne (endif、または else まで) pIfPertialSchedule = compiler.codeGenerator.op_jne( 0, sizeof(long), true ); } else if( tempType.IsSingle() ){ //fld dword ptr[esp] compiler.codeGenerator.op_fld_ptr_esp(DEF_SINGLE); //push 0 compiler.codeGenerator.op_push_V(0); //fild dword ptr[esp] compiler.codeGenerator.op_fld_ptr_esp(DEF_LONG); //add esp,sizeof(float)+sizeof(long) compiler.codeGenerator.op_add_esp(sizeof(float)+sizeof(long)); //fcompp compiler.codeGenerator.op_fcompp(); //fnstsw ax compiler.codeGenerator.op_fnstsw_ax(); //test ah,40 compiler.codeGenerator.op_test_ah( (char)0x40 ); //jne (endif、または else まで) pIfPertialSchedule = compiler.codeGenerator.op_jne( 0, sizeof(long), true ); } else if( tempType.Is64() ){ //64ビット型 //pop eax compiler.codeGenerator.op_pop(REG_EAX); //pop ebx compiler.codeGenerator.op_pop(REG_EBX); //cmp eax,0 compiler.codeGenerator.op_cmp_value( sizeof(long), REG_EAX, 0 ); //jne const PertialSchedule *pTempPertialSchedule1 = compiler.codeGenerator.op_jne( 0, sizeof(char), true ); //cmp ebx,0 compiler.codeGenerator.op_cmp_value( sizeof(long), REG_EBX, 0 ); //jne const PertialSchedule *pTempPertialSchedule2 = compiler.codeGenerator.op_jne( 0, sizeof(char), true ); //jmp (endif、または else までジャンプ) pIfPertialSchedule = compiler.codeGenerator.op_jmp( 0, sizeof(long), true ); compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule1 ); compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule2 ); } else{ //32ビット型 //pop eax compiler.codeGenerator.op_pop(REG_EAX); //cmp eax,0 compiler.codeGenerator.op_cmp_value( sizeof(long), REG_EAX, 0 ); //je (endif、または else まで条件ジャンプ) pIfPertialSchedule = compiler.codeGenerator.op_je( 0, sizeof(long), true ); } ///////////////////////// // If内をコード化 ///////////////////////// //レキシカルスコープをレベルアップ compiler.codeGenerator.lexicalScopes.Start( compiler.codeGenerator.GetNativeCodeSize(), LexicalScope::SCOPE_TYPE_IF ); i2=CompileBuffer(ESC_ENDIF,0); //レキシカルスコープをレベルダウン compiler.codeGenerator.lexicalScopes.End(); if( pIfPertialSchedule == NULL ) return; if(i2==ESC_ELSE){ //jmp (endifまで) const PertialSchedule *pTempPertialSchedule = compiler.codeGenerator.op_jmp( 0, sizeof(long), true ); compiler.codeGenerator.opfix_JmpPertialSchedule( pIfPertialSchedule ); ///////////////////////// // Else内をコード化 ///////////////////////// //レキシカルスコープをレベルアップ compiler.codeGenerator.lexicalScopes.Start( compiler.codeGenerator.GetNativeCodeSize(), LexicalScope::SCOPE_TYPE_IF ); CompileBuffer(ESC_ENDIF,0); //レキシカルスコープをレベルダウン compiler.codeGenerator.lexicalScopes.End(); compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule ); } else{ compiler.codeGenerator.opfix_JmpPertialSchedule( pIfPertialSchedule ); } } int GetLabelAddress(char *LabelName,int LineNum){ if(LabelName){ BOOST_FOREACH( const GotoLabel &label, compiler.codeGenerator.gotoLabels ) { if( label.name.size() > 0 ) { if( label.name == LabelName ) { return label.address; } } } } else{ BOOST_FOREACH( const GotoLabel &label, compiler.codeGenerator.gotoLabels ) { if( label.name.size() == 0 ) { if( label.line == LineNum ) { return label.address; } } } } return -1; } void OpcodeGoto(char *Parameter){ extern HANDLE hHeap; int i,LineNum; if(Parameter[0]=='*'){ i=GetLabelAddress(Parameter+1,0); if( i == -1 ) { //jmp ...(schedule) compiler.codeGenerator.op_jmp_goto_schedule( (const std::string)(Parameter + 1), 0, cp ); } else { //jmp ... compiler.codeGenerator.op_jmp( i-compiler.codeGenerator.GetNativeCodeSize(), sizeof(long), false, true ); } } else{ LineNum=atoi(Parameter); i=GetLabelAddress(0,LineNum); if( i == -1 ) { //jmp ...(schedule) compiler.codeGenerator.op_jmp_goto_schedule( "", LineNum, cp ); } else { //jmp ... compiler.codeGenerator.op_jmp( i-compiler.codeGenerator.GetNativeCodeSize(), sizeof(long), false, true ); } } } void OpcodeWhile(char *Parameter){ extern HANDLE hHeap; //Continueアドレスのバックアップとセット compiler.codeGenerator.ContinueAreaBegin(); if(!Parameter[0]) SetError(10,"While",cp); const PertialSchedule *pWhilePertialSchedule = NULL; Type tempType; if( !NumOpe(Parameter,Type(),tempType) ){ //ダミー } else if( tempType.IsDouble() ){ //fld qword ptr[esp] compiler.codeGenerator.op_fld_ptr_esp(DEF_DOUBLE); //push 0 compiler.codeGenerator.op_push_V(0); //fild dword ptr[esp] compiler.codeGenerator.op_fld_ptr_esp(DEF_LONG); //add esp,sizeof(double)+sizeof(long) compiler.codeGenerator.op_add_esp(sizeof(double)+sizeof(long)); //fcompp compiler.codeGenerator.op_fcompp(); //fnstsw ax compiler.codeGenerator.op_fnstsw_ax(); //test ah,40 compiler.codeGenerator.op_test_ah( (char)0x40 ); //jne (Wend まで) pWhilePertialSchedule = compiler.codeGenerator.op_jne( 0, sizeof(long), true ); } else if( tempType.IsSingle() ){ //fld dword ptr[esp] compiler.codeGenerator.op_fld_ptr_esp(DEF_SINGLE); //push 0 compiler.codeGenerator.op_push_V(0); //fild dword ptr[esp] compiler.codeGenerator.op_fld_ptr_esp(DEF_LONG); //add esp,sizeof(float)+sizeof(long) compiler.codeGenerator.op_add_esp(sizeof(float)+sizeof(long)); //fcompp compiler.codeGenerator.op_fcompp(); //fnstsw ax compiler.codeGenerator.op_fnstsw_ax(); //test ah,40h compiler.codeGenerator.op_test_ah( (char)0x40 ); //jne (Wend まで) pWhilePertialSchedule = compiler.codeGenerator.op_jne( 0, sizeof(long), true ); } else if( tempType.Is64() ){ //64ビット型 //pop eax compiler.codeGenerator.op_pop(REG_EAX); //pop ebx compiler.codeGenerator.op_pop(REG_EBX); //cmp eax,0 compiler.codeGenerator.op_cmp_value( sizeof(long), REG_EAX, 0 ); //jne const PertialSchedule *pTempPertialSchedule1 = compiler.codeGenerator.op_jne( 0, sizeof(char), true ); //cmp ebx,0 compiler.codeGenerator.op_cmp_value( sizeof(long), REG_EBX, 0 ); //jne const PertialSchedule *pTempPertialSchedule2 = compiler.codeGenerator.op_jne( 0, sizeof(char), true ); //jmp (Wendまでジャンプ) pWhilePertialSchedule = compiler.codeGenerator.op_jmp( 0, sizeof(long), true ); compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule1 ); compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule2 ); } else{ //その他整数型 //pop eax compiler.codeGenerator.op_pop(REG_EAX); //cmp eax,0 compiler.codeGenerator.op_cmp_value( sizeof(long), REG_EAX, 0 ); //je (Wend まで) pWhilePertialSchedule = compiler.codeGenerator.op_je( 0, sizeof(long), true ); } //レキシカルスコープをレベルアップ compiler.codeGenerator.lexicalScopes.Start( compiler.codeGenerator.GetNativeCodeSize(), LexicalScope::SCOPE_TYPE_WHILE ); //While内をコンパイル CompileBuffer(0,COM_WEND); compiler.codeGenerator.lexicalScopes.CallDestructorsOfScopeEnd(); //jmp ... compiler.codeGenerator.op_jmp_continue(); //レキシカルスコープをレベルダウン compiler.codeGenerator.lexicalScopes.End(); if( pWhilePertialSchedule ) { compiler.codeGenerator.opfix_JmpPertialSchedule( pWhilePertialSchedule ); } compiler.codeGenerator.ContinueAreaEnd(); } char szNextVariable[VN_SIZE]; void OpcodeFor(char *Parameter){ extern HANDLE hHeap; int i,i2; char temporary[VN_SIZE],variable[VN_SIZE],JudgeNum[VN_SIZE],StepNum[VN_SIZE]; //第1パラメータを取得 i=GetOneParameter(Parameter,0,temporary); if(!Parameter[i]){ SetError(12,"For",cp); goto ErrorStep; } for(i2=0;;i2++){ if(temporary[i2]=='='){ variable[i2]=0; //カウンタ初期化 OpcodeCalc(temporary); break; } if(temporary[i2]=='\0'){ SetError(12,"For",cp); goto ErrorStep; } variable[i2]=temporary[i2]; } //jmp ... const PertialSchedule *pTempPertialSchedule = compiler.codeGenerator.op_jmp( 0, sizeof(long), true ); //Continueアドレスのバックアップとセット compiler.codeGenerator.ContinueAreaBegin(); //第2パラメータを取得(to〜) i=GetOneParameter(Parameter,i,JudgeNum); //第3パラメータを取得(step〜) if(Parameter[i]){ i=GetOneParameter(Parameter,i,StepNum); if(Parameter[i]) SetError(12,"For",cp); } else lstrcpy(StepNum,"1"); //カウンタを増加させる sprintf(temporary,"%s=(%s)+(%s)",variable,variable,StepNum); OpcodeCalc(temporary); compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule ); //増加か減少かを区別する sprintf(temporary,"(%s)>=0",StepNum); NumOpe(temporary,Type(),Type()); //pop eax compiler.codeGenerator.op_pop(REG_EAX); //cmp eax,0 compiler.codeGenerator.op_cmp_value( sizeof(long), REG_EAX, 0 ); //je [カウンタ減少の場合の判定] pTempPertialSchedule = compiler.codeGenerator.op_je( 0, sizeof(long), true ); //判定(カウンタ増加の場合) sprintf(temporary,"%s<=(%s)",variable,JudgeNum); NumOpe(temporary,Type(),Type()); //pop eax compiler.codeGenerator.op_pop(REG_EAX); //jmp [カウンタ減少の場合の判定を飛び越す] const PertialSchedule *pTempPertialSchedule2 = compiler.codeGenerator.op_jmp( 0, sizeof(long), true ); //jeジャンプ先のオフセット値 compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule ); //判定(カウンタ減少の場合) sprintf(temporary,"%s>=(%s)",variable,JudgeNum); NumOpe(temporary,Type(),Type()); //pop eax compiler.codeGenerator.op_pop(REG_EAX); //jmpジャンプ先のオフセット値 compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule2 ); //cmp eax,0 compiler.codeGenerator.op_cmp_value( sizeof(long), REG_EAX, 0 ); ErrorStep: //je ... pTempPertialSchedule = compiler.codeGenerator.op_je( 0, sizeof(long), true ); //レキシカルスコープをレベルアップ compiler.codeGenerator.lexicalScopes.Start( compiler.codeGenerator.GetNativeCodeSize(), LexicalScope::SCOPE_TYPE_FOR ); //For内をコンパイル CompileBuffer(0,COM_NEXT); compiler.codeGenerator.lexicalScopes.CallDestructorsOfScopeEnd(); if(szNextVariable[0]){ if(lstrcmp(szNextVariable,variable)!=0){ SetError(55,szNextVariable,cp); } } //jmp ... compiler.codeGenerator.op_jmp_continue(); //レキシカルスコープをレベルダウン compiler.codeGenerator.lexicalScopes.End(); //jeジャンプ先のオフセット値 compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule ); //Continueアドレスを復元 compiler.codeGenerator.ContinueAreaEnd(); } void OpcodeForeach( const char *Parameter ) { Type resultType; char temporary[VN_SIZE],variable[VN_SIZE],collectionVar[VN_SIZE]; bool isError = false; //レキシカルスコープをレベルアップ compiler.codeGenerator.lexicalScopes.Start( compiler.codeGenerator.GetNativeCodeSize(), LexicalScope::SCOPE_TYPE_FOR ); //第1パラメータを取得 int i = 0; GetCustomToken( variable, Parameter, i, ESC_IN, true ); if(!Parameter[i]){ SetError(12,"Foreach",cp); isError = true; goto ErrorStep; } i++; //第2パラメータを取得(in〜) lstrcpy( collectionVar, Parameter + i ); if( !GetVarType( variable, resultType, false ) ) { Type collectionType; if( !NumOpe_GetType( collectionVar, Type(), collectionType ) ) { isError = true; goto ErrorStep; } // 未定義の場合は自動的に定義する sprintf(temporary,"%s=Nothing%c%c%s", variable, 1, ESC_AS, collectionType.GetActualGenericType(0).GetClass().GetFullName().c_str() ); OpcodeDim(temporary,DIMFLAG_INITDEBUGVAR); } // Resetメソッドを呼び出す sprintf( temporary, "%s.Reset()", collectionVar ); Compile( temporary ); //Continueアドレスのバックアップとセット compiler.codeGenerator.ContinueAreaBegin(); // MoveNextメソッドを呼び出す sprintf( temporary, "%s.MoveNext()", collectionVar ); NumOpe(temporary,Type(),Type()); //pop eax compiler.codeGenerator.op_pop(REG_EAX); //cmp eax,0 compiler.codeGenerator.op_cmp_value( sizeof(long), REG_EAX, 0 ); ErrorStep: //je ... const PertialSchedule *pTempPertialSchedule = compiler.codeGenerator.op_je( 0, sizeof(long), true ); if( !isError ) { // Currentプロパティから現在の値を取得 sprintf( temporary, "%s=%s.Current", variable, collectionVar ); Compile( temporary ); } //For内をコンパイル CompileBuffer(0,COM_NEXT); compiler.codeGenerator.lexicalScopes.CallDestructorsOfScopeEnd(); if(szNextVariable[0]){ if(lstrcmp(szNextVariable,variable)!=0){ SetError(55,szNextVariable,cp); } } if( !isError ) { //jmp ... compiler.codeGenerator.op_jmp_continue(); } //レキシカルスコープをレベルダウン compiler.codeGenerator.lexicalScopes.End(); //jeジャンプ先のオフセット値 compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule ); //Continueアドレスを復元 compiler.codeGenerator.ContinueAreaEnd(); } void OpcodeDo(char *Parameter){ extern HANDLE hHeap; int i,i2,i3; if(Parameter[0]) SetError(10,"Do",cp); //Continueアドレスのバックアップとセット compiler.codeGenerator.ContinueAreaBegin(); //レキシカルスコープをレベルアップ compiler.codeGenerator.lexicalScopes.Start( compiler.codeGenerator.GetNativeCodeSize(), LexicalScope::SCOPE_TYPE_DO ); //Do内をコンパイル CompileBuffer(0,COM_LOOP); compiler.codeGenerator.lexicalScopes.CallDestructorsOfScopeEnd(); const PertialSchedule *pDoPertialSchedule = NULL; extern char *basbuf; char temporary[VN_SIZE]; for(i=cp-1;;i--){ if(IsCommandDelimitation(basbuf[i])){ i+=3; if(!(basbuf[i]=='0'||basbuf[i]=='1')){ //無条件ループ break; } i3=i; for(i+=2,i2=0;;i++,i2++){ if(IsCommandDelimitation(basbuf[i])){ temporary[i2]=0; break; } temporary[i2]=basbuf[i]; } Type tempType; NumOpe(temporary,Type(),tempType); if( tempType.IsDouble() ){ //fld qword ptr[esp] compiler.codeGenerator.op_fld_ptr_esp(DEF_DOUBLE); //push 0 compiler.codeGenerator.op_push_V(0); //fild dword ptr[esp] compiler.codeGenerator.op_fld_ptr_esp(DEF_LONG); //add esp,sizeof(double)+sizeof(long) compiler.codeGenerator.op_add_esp(sizeof(double)+sizeof(long)); //fcompp compiler.codeGenerator.op_fcompp(); //fnstsw ax compiler.codeGenerator.op_fnstsw_ax(); //test ah,40 compiler.codeGenerator.op_test_ah( (char)0x40 ); if(basbuf[i3]=='0'){ //While //jne 5(ループ終了) pDoPertialSchedule = compiler.codeGenerator.op_jne( 0, sizeof(char), true ); } else if(basbuf[i3]=='1'){ //Until //je 5(ループ終了) pDoPertialSchedule = compiler.codeGenerator.op_je( 0, sizeof(char), true ); } } else if( tempType.IsSingle() ){ //fld dword ptr[esp] compiler.codeGenerator.op_fld_ptr_esp(DEF_SINGLE); //push 0 compiler.codeGenerator.op_push_V(0); //fild dword ptr[esp] compiler.codeGenerator.op_fld_ptr_esp(DEF_LONG); //add esp,sizeof(float)+sizeof(long) compiler.codeGenerator.op_add_esp(sizeof(float)+sizeof(long)); //fcompp compiler.codeGenerator.op_fcompp(); //fnstsw ax compiler.codeGenerator.op_fnstsw_ax(); //test ah,40 compiler.codeGenerator.op_test_ah( (char)0x40 ); if(basbuf[i3]=='0'){ //While //jne 5(ループ終了) pDoPertialSchedule = compiler.codeGenerator.op_jne( 0, sizeof(char), true ); } else if(basbuf[i3]=='1'){ //Until //je 5(ループ終了) pDoPertialSchedule = compiler.codeGenerator.op_je( 0, sizeof(char), true ); } } else if( tempType.Is64() ){ //64ビット型 //pop eax compiler.codeGenerator.op_pop(REG_EAX); //pop ebx compiler.codeGenerator.op_pop(REG_EBX); //cmp eax,0 compiler.codeGenerator.op_cmp_value( sizeof(long), REG_EAX, 0 ); //jne const PertialSchedule *pTempPertialSchedule1 = compiler.codeGenerator.op_jne( 0, sizeof(char), true ); //cmp ebx,0 compiler.codeGenerator.op_cmp_value( sizeof(long), REG_EBX, 0 ); //jne const PertialSchedule *pTempPertialSchedule2 = compiler.codeGenerator.op_jne( 0, sizeof(char), true ); if(basbuf[i3]=='0'){ //While //jmp 5(ループ終了) pDoPertialSchedule = compiler.codeGenerator.op_jmp( 0, sizeof(char), true ); compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule1 ); compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule2 ); } else if(basbuf[i3]=='1'){ //Until //jmp 2(ループを続ける) const PertialSchedule *pTempPertialSchedule3 = compiler.codeGenerator.op_jmp( 0, sizeof(char), true ); compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule1 ); compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule2 ); //jmp 5(ループ終了) pDoPertialSchedule = compiler.codeGenerator.op_jmp( 0, sizeof(char), true ); compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule3 ); } } else{ //pop eax compiler.codeGenerator.op_pop(REG_EAX); //cmp eax,0 compiler.codeGenerator.op_cmp_value( sizeof(long), REG_EAX, 0 ); if(basbuf[i3]=='0'){ //While //je 5(ループ終了) pDoPertialSchedule = compiler.codeGenerator.op_je( 0, sizeof(char), true ); } else if(basbuf[i3]=='1'){ //Until //jne 5(ループ終了) pDoPertialSchedule = compiler.codeGenerator.op_jne( 0, sizeof(char), true ); } } break; } } //jmp ... compiler.codeGenerator.op_jmp_continue(); if( pDoPertialSchedule ) { compiler.codeGenerator.opfix_JmpPertialSchedule( pDoPertialSchedule ); } //jmp ... const PertialSchedule *pTempPertialSchedule = compiler.codeGenerator.op_jmp( 0, sizeof(long), true ); //レキシカルスコープをレベルダウン compiler.codeGenerator.lexicalScopes.End(); //jmpジャンプ先のオフセット値 compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule ); //Continueアドレスを復元 compiler.codeGenerator.ContinueAreaEnd(); } void OpcodeContinue(void){ //jmp ...(Continue addr) compiler.codeGenerator.op_jmp_continue(); } void OpcodeExitSub(void){ if( UserProc::IsGlobalAreaCompiling() ){ SetError(12,"Exit Sub/Function",cp); return; } //未解放のローカルオブジェクトのデストラクタを呼び出す compiler.codeGenerator.lexicalScopes.CallDestructorsOfReturn(); //jmp ...(End Sub/Function) compiler.codeGenerator.op_jmp_exitsub(); } //Caseスケジュール class SelectSchedule { public: SelectSchedule( int typeSize ) : typeSize( typeSize ) , nowCaseSchedule( 0 ) { } PertialSchedules casePertialSchedules; int typeSize; int nowCaseSchedule; }; std::vector selectSchedules; void OpcodeSelect(const char *lpszParms){ extern HANDLE hHeap; extern char *basbuf; int i,i2,i3,sw,NowCaseCp; char temporary[VN_SIZE]; Type type1; if( !NumOpe(lpszParms,Type(), type1 ) ){ return; } selectSchedules.push_back( SelectSchedule( type1.GetSize() ) ); if( selectSchedules.back().typeSize < sizeof(long) ){ selectSchedules.back().typeSize = sizeof(long); } for(i=cp,sw=0;;i++){ if(basbuf[i]=='\0'){ selectSchedules.pop_back(); SetError(22,"Select",cp); return; } if(basbuf[i]==1&&basbuf[i+1]==ESC_SELECTCASE){ for(i2=0;;i++){ if(basbuf[i]==1&&basbuf[i+1]==ESC_SELECTCASE) i2++; if(basbuf[i]==1&&basbuf[i+1]==ESC_ENDSELECT){ i2--; if(i2==0) break; } } continue; } if(basbuf[i]==1&&basbuf[i+1]==ESC_ENDSELECT){ if(sw==0){ //add esp,CaseTypeSize compiler.codeGenerator.op_add_esp( selectSchedules.back().typeSize ); } break; } if(basbuf[i]==1&&basbuf[i+1]==ESC_CASE){ NowCaseCp=i; i++; while(1){ for(i++,i2=0;;i++,i2++){ if(basbuf[i]=='\"'){ i3=GetStringInQuotation(temporary+i2,basbuf+i); i+=i3-1; i2+=i3-1; continue; } if(basbuf[i]=='('){ i3=GetStringInPare(temporary+i2,basbuf+i); i+=i3-1; i2+=i3-1; continue; } if(basbuf[i]=='['){ i3=GetStringInBracket(temporary+i2,basbuf+i); i+=i3-1; i2+=i3-1; continue; } if(IsCommandDelimitation(basbuf[i])){ temporary[i2]=0; break; } if(basbuf[i]==','){ temporary[i2]=0; break; } temporary[i2]=basbuf[i]; } //エラー用 i2=cp; cp=NowCaseCp; Type type2; if( !NumOpe(temporary,type1,type2) ){ return; } cp=i2; if(type1.IsObject()){ std::vector subs; type1.GetClass().GetDynamicMethods().Enum( CALC_EQUAL, subs ); if( subs.size() == 0 ){ return; } Parameters params; params.push_back( new Parameter( "", Type( type2 ) ) ); //オーバーロードを解決 const UserProc *pUserProc = OverloadSolution("==",subs, params, NULL); delete params[0]; if(!pUserProc){ //エラー return; } //pop edx compiler.codeGenerator.op_pop(REG_EDX); //mov ecx,dword ptr[esp] compiler.codeGenerator.op_mov_RM(sizeof(long),REG_ECX,REG_ESP,0,MOD_BASE); //push edx compiler.codeGenerator.op_push(REG_EDX); //push ecx compiler.codeGenerator.op_push(REG_ECX); //call operator_proc ※ ==演算子 compiler.codeGenerator.op_call(pUserProc); //test eax,eax compiler.codeGenerator.op_test(REG_EAX,REG_EAX); //jne ... selectSchedules.back().casePertialSchedules.push_back( compiler.codeGenerator.op_jne( 0, sizeof(long), true ) ); } else if(type1.IsDouble()){ ChangeTypeToDouble(type2.GetBasicType()); //fld qword ptr[esp] compiler.codeGenerator.op_fld_ptr_esp(DEF_DOUBLE); //add esp,CaseTypeSize compiler.codeGenerator.op_add_esp(selectSchedules.back().typeSize); //fld qword ptr[esp] compiler.codeGenerator.op_fld_ptr_esp(DEF_DOUBLE); //fcompp compiler.codeGenerator.op_fcompp(); //fnstsw ax compiler.codeGenerator.op_fnstsw_ax(); //test ah,40 compiler.codeGenerator.op_test_ah( (char)0x40 ); //jne ... selectSchedules.back().casePertialSchedules.push_back( compiler.codeGenerator.op_jne( 0, sizeof(long), true ) ); } else if(type1.IsSingle()){ ChangeTypeToSingle(type2.GetBasicType()); //fld dword ptr[esp] compiler.codeGenerator.op_fld_ptr_esp(DEF_SINGLE); //add esp,CaseTypeSize compiler.codeGenerator.op_add_esp(selectSchedules.back().typeSize); //fld dword ptr[esp] compiler.codeGenerator.op_fld_ptr_esp(DEF_SINGLE); //fcompp compiler.codeGenerator.op_fcompp(); //fnstsw ax compiler.codeGenerator.op_fnstsw_ax(); //test ah,40 compiler.codeGenerator.op_test_ah( (char)0x40 ); //jne ... selectSchedules.back().casePertialSchedules.push_back( compiler.codeGenerator.op_jne( 0, sizeof(long), true ) ); } else{ //その他整数型 //pop ebx compiler.codeGenerator.op_pop(REG_EBX); //mov eax,dword ptr[esp] compiler.codeGenerator.op_mov_RM( sizeof(long), REG_EAX, REG_ESP, 0, MOD_BASE ); //cmp eax,ebx compiler.codeGenerator.op_cmp_RR( REG_EAX, REG_EBX ); //je ... selectSchedules.back().casePertialSchedules.push_back( compiler.codeGenerator.op_je( 0, sizeof(long), true ) ); } if(basbuf[i]!=',') break; } } if(basbuf[i]==1&&basbuf[i+1]==ESC_CASEELSE){ sw=1; //jmp ... selectSchedules.back().casePertialSchedules.push_back( compiler.codeGenerator.op_jmp( 0, sizeof(long), true ) ); } } //レキシカルスコープをレベルアップ compiler.codeGenerator.lexicalScopes.Start( compiler.codeGenerator.GetNativeCodeSize(), LexicalScope::SCOPE_TYPE_SELECT ); //Select Case内をコンパイル CompileBuffer(ESC_ENDSELECT,0); //jmp EndSelect selectSchedules.back().casePertialSchedules.push_back( compiler.codeGenerator.op_jmp( 0, sizeof(long), true ) ); //最終スケジュール for(i=selectSchedules.back().nowCaseSchedule;i<(int)selectSchedules.back().casePertialSchedules.size();i++){ compiler.codeGenerator.opfix_JmpPertialSchedule( selectSchedules.back().casePertialSchedules[i] ); } //レキシカルスコープをレベルダウン compiler.codeGenerator.lexicalScopes.End(); selectSchedules.pop_back(); } void OpcodeCase(char *Parameter){ int i; if(selectSchedules.back().typeSize==-1){ SetError(30,"Case",cp); return; } //jmp EndSelect selectSchedules.back().casePertialSchedules.push_back( compiler.codeGenerator.op_jmp( 0, sizeof(long), true ) ); i=0; while(1){ //Caseスケジュール compiler.codeGenerator.opfix_JmpPertialSchedule( selectSchedules.back().casePertialSchedules[selectSchedules.back().nowCaseSchedule] ); selectSchedules.back().nowCaseSchedule++; i=JumpOneParameter(Parameter,i); if(Parameter[i]=='\0') break; } //add esp,CaseTypeSize compiler.codeGenerator.op_add_esp(selectSchedules.back().typeSize); } void OpcodeGosub(char *Parameter){ extern HANDLE hHeap; int i,LineNum; if(Parameter[0]=='*'){ i=GetLabelAddress(Parameter+1,0); if( i == -1 ) { //jmp ...(schedule) compiler.codeGenerator.op_jmp_goto_schedule( (const std::string)(Parameter + 1), 0, cp ); } else { //jmp ... compiler.codeGenerator.op_jmp( i-compiler.codeGenerator.GetNativeCodeSize(), sizeof(long), false, true ); } } else{ LineNum=atoi(Parameter); i=GetLabelAddress(0,LineNum); if( i == -1 ) { //jmp ...(schedule) compiler.codeGenerator.op_jmp_goto_schedule( "", LineNum, cp ); } else { //jmp ... compiler.codeGenerator.op_jmp( i-compiler.codeGenerator.GetNativeCodeSize(), sizeof(long), false, true ); } } } void OpcodeReturn(char *Parameter){ if( UserProc::IsGlobalAreaCompiling() ){ //Gosub〜Returnとして扱う //ret compiler.codeGenerator.op_ret(); } else{ //戻り値をセット if(Parameter[0]){ const UserProc &proc = UserProc::CompilingUserProc(); const char *temp = "_System_ReturnValue"; if(proc.GetName()[0]==1&&proc.GetName()[1]==ESC_OPERATOR) { } else{ temp=proc.GetName().c_str(); } char temporary[VN_SIZE]; sprintf(temporary,"%s=%s",temp,Parameter); OpcodeCalc(temporary); } //プロシージャを抜け出す(C言語のreturnと同様の処理を行う) OpcodeExitSub(); } } //////////// // ポインタ void OpcodeSetPtrData(char *Parameter,int type){ int i; char temporary[VN_SIZE]; if(Parameter[0]=='('){ i=JumpStringInPare(Parameter,1); if(Parameter[i+1]=='\0'){ for(i=0;;i++){ Parameter[i]=Parameter[i+1]; if(Parameter[i]=='\0') break; } Parameter[i-1]=0; } } //第1パラメータを取得 i=GetOneParameter(Parameter,0,temporary); if(!Parameter[i]){ SetError(1,NULL,cp); return; } Type resultType; if( !NumOpe(temporary,Type(),resultType) ){ return; } if(!resultType.IsWhole()){ SetError(11,Parameter,cp); return; } ChangeTypeToLong( resultType.GetBasicType() ); //第2パラメータを取得 i=GetOneParameter(Parameter,i,temporary); if(Parameter[i]){ SetError(1,NULL,cp); return; } if( !NumOpe(temporary,Type(),resultType) ){ return; } if(type==DEF_DOUBLE){ ChangeTypeToDouble_ToFpuReg( resultType.GetBasicType() ); //pop eax compiler.codeGenerator.op_pop(REG_EAX); //fstp qword ptr[eax] compiler.codeGenerator.PutOld( (char)0xDD, (char)0x18 ); } else if(type==DEF_SINGLE){ ChangeTypeToSingle( resultType.GetBasicType() ); //pop ebx compiler.codeGenerator.op_pop(REG_EBX); //pop eax compiler.codeGenerator.op_pop(REG_EAX); //mov dword ptr[eax],ebx compiler.codeGenerator.op_mov_MR( sizeof(long), REG_EBX, REG_EAX, 0, MOD_BASE ); } else if(type==DEF_QWORD){ ChangeTypeToInt64( resultType.GetBasicType() ); //pop ecx compiler.codeGenerator.op_pop(REG_ECX); //pop ebx compiler.codeGenerator.op_pop(REG_EBX); //pop eax compiler.codeGenerator.op_pop(REG_EAX); //mov dword ptr[eax],ecx compiler.codeGenerator.op_mov_MR( sizeof(long), REG_ECX, REG_EAX, 0, MOD_BASE ); //mov dword ptr[eax+sizeof(long)],ebx compiler.codeGenerator.op_mov_MR( sizeof(long), REG_EBX, REG_EAX, 0x04, MOD_BASE_DISP8 ); } else if(type==DEF_DWORD){ ChangeTypeToLong( resultType.GetBasicType() ); //pop ebx compiler.codeGenerator.op_pop(REG_EBX); //pop eax compiler.codeGenerator.op_pop(REG_EAX); //mov dword ptr[eax],ebx compiler.codeGenerator.op_mov_MR( sizeof(long), REG_EBX, REG_EAX, 0, MOD_BASE ); } else if(type==DEF_WORD){ ChangeTypeToLong( resultType.GetBasicType() ); //pop ebx compiler.codeGenerator.op_pop(REG_EBX); //pop eax compiler.codeGenerator.op_pop(REG_EAX); //mov word ptr[eax],bx compiler.codeGenerator.op_mov_MR( sizeof(short), REG_EBX, REG_EAX, 0, MOD_BASE ); } else if(type==DEF_BYTE){ ChangeTypeToLong( resultType.GetBasicType() ); //pop ebx compiler.codeGenerator.op_pop(REG_EBX); //pop eax compiler.codeGenerator.op_pop(REG_EAX); //mov byte ptr[eax],bl compiler.codeGenerator.op_mov_MR( sizeof(char), REG_EBX, REG_EAX, 0, MOD_BASE ); } }