#include "stdafx.h" #include #include #include #include "../BasicCompiler_Common/common.h" #ifdef _AMD64_ #include "../compiler_x64/opcode.h" #else #include "../compiler_x86/opcode.h" #endif //With情報 WITHINFO WithInfo; //デバッグ用行番号情報 SourceLines oldSourceLines; // オブジェクトモジュールリストに類似したソースコードリスト BasicSources sourcesLinkRelationalObjectModule; /////////////////////////////////////////////////// // トークンを取得 /////////////////////////////////////////////////// void GetIdentifierToken( char *token, const char *source, int &pos ) { for( int i=0; ; i++, pos++ ){ if( ! IsVariableChar( source[pos] ) ){ token[i] = 0; break; } token[i] = source[pos]; } } void GetCommandToken( char *token, const char *source, int &pos ) { for( int i=0; ; i++, pos++ ){ if( IsCommandDelimitation( source[pos] ) ){ token[i] = 0; break; } token[i] = source[pos]; } } void GetCustomToken( char *token, const char *source, int &pos, char delimitation, bool isEscapeSequence ) { for( int i=0; ; i++, pos++ ){ if( isEscapeSequence ) { if( source[pos] == 1 && source[pos+1] == delimitation ) { token[i] = 0; pos++; break; } } else { if( source[pos] == delimitation ) { token[i] = 0; break; } } token[i] = source[pos]; if( source[pos] == '\0' ) { break; } } } /////////////////////////////////////////////////// // ジェネリクスのクラス型記述を分析 /////////////////////////////////////////////////// void SplitGenericClassInstance( const char *fullName, char *className, Jenga::Common::Strings &typeParameters, bool isDefiningClass, Jenga::Common::Strings *pTypeParameterBaseClassNames ) { if( isDefiningClass ) { if( !pTypeParameterBaseClassNames ) { compiler.errorMessenger.OutputFatalError(); } pTypeParameterBaseClassNames->clear(); } int i = 0; typeParameters.clear(); //クラス名を取得 GetIdentifierToken( className, fullName, i ); ///////////////////////////////////////////////////////// // ☆★☆ ジェネリクスサポート ☆★☆ if( fullName[i] == '<' ) { while( true ) { i++; // 型パラメータを取得 char temporary[VN_SIZE]; GetIdentifierToken( temporary, fullName, i ); if( temporary[0] == '\0' ) { extern int cp; compiler.errorMessenger.Output(1,NULL,cp); } typeParameters.push_back( temporary ); if( isDefiningClass ) { // クラス定義中にこの関数が呼び出されたとき if( fullName[i] == 1 && fullName[i+1] == ESC_AS ) { // 型パラメータの制約クラスを取得 i += 2; GetIdentifierToken( temporary, fullName, i ); if( temporary[0] == '\0' ) { extern int cp; compiler.errorMessenger.Output(1,NULL,cp); } } else { temporary[0] = 0; } pTypeParameterBaseClassNames->push_back( temporary ); } if( fullName[i] == ',' ) { continue; } else if( fullName[i] == '>' ) { break; } else { extern int cp; compiler.errorMessenger.Output(1,NULL,cp); } } } ///////////////////////////////////////////////////////// } /////////////////////////////////////////////////// // 対になっているステートメントを飛び越す // ※グローバル領域用 /////////////////////////////////////////////////// int JumpStatement(const char *source, int &pos){ if( source[pos] != 1 ) return 0; if( ! IsCommandDelimitation( source[pos - 1] ) ){ //直前がコマンド区切りではない場合 return 0; } char cStatement = source[pos + 1]; char cEnd = GetEndXXXCommand( cStatement ); if( cEnd == 0 ) return 0; pos += 2; while( ! ( source[pos] == 1 && source[pos + 1] == cEnd ) ){ if( source[pos] == '\0' ){ char temporary[64]; GetDefaultNameFromES( cStatement, temporary ); compiler.errorMessenger.Output( 22, temporary, pos ); return -1; } pos++; } if( ! ( source[pos] == '\0' || source[pos + 2] == '\0' ) ){ pos += 2; } return 1; } void Compile( const char *source ) { char *temporary = (char *)malloc( lstrlen( source ) + 8192 ); lstrcpy( temporary, source ); int backCp = cp; MakeMiddleCode( temporary ); cp = backCp; ChangeOpcode( temporary ); cp = backCp; free( temporary ); } void ChangeOpcode(char *Command){ extern HANDLE hHeap; if(Command[0]=='\0') { return; } trace_for_sourcecodestep( FormatEscapeSequenceStringToDefaultString(Command) ); if(Command[0]=='*'&&IsVariableTopChar(Command[1])){ //Goto先ラベル compiler.codeGenerator.gotoLabels.push_back( GotoLabel( Command + 1, compiler.codeGenerator.GetNativeCodeSize() ) ); //書き込みスケジュール GotoLabelSchedules::iterator it = compiler.codeGenerator.gotoLabelSchedules.begin(); while( it != compiler.codeGenerator.gotoLabelSchedules.end() ) { if( (*it)->GetName() == Command+1 ) { compiler.codeGenerator.opfix_JmpPertialSchedule( (*it) ); //詰める it = compiler.codeGenerator.gotoLabelSchedules.erase( it ); } else { it++; } } return; } if(Command[0]==1){ switch(Command[1]){ case ESC_CONST: OpcodeDim(Command+2, DIMFLAG_CONST); break; case ESC_TYPEDEF: if( compiler.IsLocalAreaCompiling() ){ // ローカル領域をコンパイルしているとき compiler.errorMessenger.Output(65,"TypeDef",cp ); } //既に収集済み break; case ESC_DELEGATE: if( compiler.IsLocalAreaCompiling() ){ // ローカル領域をコンパイルしているとき compiler.errorMessenger.Output(65,"Delegate",cp ); } //既に収集済み break; case ESC_STATIC: OpcodeDim(Command+2,DIMFLAG_STATIC); break; case ESC_IF: OpcodeIf(Command+2); break; case ESC_EXITWHILE: { LexicalScope *pScope = compiler.codeGenerator.lexicalScopes.SearchScope( LexicalScope::SCOPE_TYPE_WHILE ); if( !pScope ){ compiler.errorMessenger.Output(12,"Exit While",cp); return; } pScope->Break(); } break; case ESC_EXITFOR: { LexicalScope *pScope = compiler.codeGenerator.lexicalScopes.SearchScope( LexicalScope::SCOPE_TYPE_FOR ); if( !pScope ){ compiler.errorMessenger.Output(12,"Exit For",cp); return; } pScope->Break(); } break; case ESC_EXITDO: { LexicalScope *pScope = compiler.codeGenerator.lexicalScopes.SearchScope( LexicalScope::SCOPE_TYPE_DO ); if( !pScope ){ compiler.errorMessenger.Output(12,"Exit Do",cp); return; } pScope->Break(); } break; case ESC_CONTINUE: OpcodeContinue(); break; case ESC_EXITSUB: case ESC_EXITFUNCTION: case ESC_EXITMACRO: OpcodeExitSub(); break; case ESC_SELECTCASE: OpcodeSelect(Command+2); break; case ESC_CASE: case ESC_CASEELSE: OpcodeCase(Command+2); break; case ESC_WITH: extern WITHINFO WithInfo; WithInfo.ppName=(char **)HeapReAlloc(hHeap,0,WithInfo.ppName,(WithInfo.num+1)*sizeof(char **)); WithInfo.ppName[WithInfo.num]=(char *)HeapAlloc(hHeap,0,lstrlen(Command+2)+1); lstrcpy(WithInfo.ppName[WithInfo.num],Command+2); WithInfo.pWithCp=(int *)HeapReAlloc(hHeap,0,WithInfo.pWithCp,(WithInfo.num+1)*sizeof(int)); WithInfo.pWithCp[WithInfo.num]=cp; WithInfo.num++; break; case ESC_ENDWITH: if(WithInfo.num<=0){ compiler.errorMessenger.Output(12,"End With",cp); return; } WithInfo.num--; HeapDefaultFree(WithInfo.ppName[WithInfo.num]); break; case ESC_DECLARE: if( compiler.IsLocalAreaCompiling() ){ // ローカル領域をコンパイルしているとき compiler.errorMessenger.Output(65,"Declare",cp ); } break; case ESC_NAMESPACE: compiler.GetNamespaceSupporter().GetLivingNamespaceScopes().push_back( Command + 2 ); break; case ESC_ENDNAMESPACE: if( compiler.GetNamespaceSupporter().GetLivingNamespaceScopes().size() <= 0 ){ compiler.errorMessenger.Output(12,"End Namespace",cp); } compiler.GetNamespaceSupporter().GetLivingNamespaceScopes().pop_back(); break; case ESC_IMPORTS: compiler.GetNamespaceSupporter().ImportsNamespace( Command + 2 ); break; case ESC_CLEARNAMESPACEIMPORTED: compiler.GetNamespaceSupporter().GetImportedNamespaces().clear(); break; //Tryによる例外処理 case ESC_TRY: Exception::TryCommand(); break; case ESC_CATCH: Exception::CatchCommand( Command + 2 ); break; case ESC_FINALLY: Exception::FinallyCommand(); break; case ESC_ENDTRY: Exception::EndTryCommand(); break; case ESC_THROW: Exception::ThrowCommand( Command + 2 ); break; default: char temporary[64]; GetDefaultNameFromES(Command[1],temporary); compiler.errorMessenger.Output(30,temporary,cp); break; } return; } switch(MAKEWORD(Command[1],Command[0])){ case COM_DIM: OpcodeDim(Command+2,0); break; case COM_DELETE: OpcodeDelete(Command+2, false); break; case COM_SWEEPINGDELETE: OpcodeDelete(Command+2, true); break; case COM_GOTO: OpcodeGoto(Command+2); break; case COM_WHILE: OpcodeWhile(Command+2); break; case COM_FOR: OpcodeFor(Command+2); break; case COM_FOREACH: OpcodeForeach(Command+2); break; case COM_DO: OpcodeDo(Command+2); break; case COM_GOSUB: OpcodeGosub(Command+2); break; case COM_RETURN: OpcodeReturn(Command+2); break; case COM_SETDOUBLE: OpcodeSetPtrData(Command+2,DEF_DOUBLE); break; case COM_SETSINGLE: OpcodeSetPtrData(Command+2,DEF_SINGLE); break; case COM_SETQWORD: OpcodeSetPtrData(Command+2,DEF_QWORD); break; case COM_SETDWORD: OpcodeSetPtrData(Command+2,DEF_DWORD); break; case COM_SETWORD: OpcodeSetPtrData(Command+2,DEF_WORD); break; case COM_SETBYTE: OpcodeSetPtrData(Command+2,DEF_BYTE); break; case COM_DEBUG: //int 3 if( compiler.IsDebug() ) { breakpoint; } else { //#if defined(_DEBUG) breakpoint; //#endif } break; case COM_LET: OpcodeCalc(Command+2); break; default: OpcodeOthers(Command); // コード生成過程で発生した構造体の一時メモリを破棄する compiler.codeGenerator.op_FreeTempStructure(); break; } } void GetGlobalDataForDll(void){ extern char *basbuf; extern HANDLE hHeap; int i2,BufferSize; char *Command; DWORD dwRetCode; dwRetCode=0; BufferSize=128; Command=(char *)HeapAlloc(hHeap,0,BufferSize); for(cp++,i2=0;;cp++,i2++){ if(i2>=BufferSize){ //バッファ領域が足りなくなった場合はバッファを増量する BufferSize+=128; Command=(char *)HeapReAlloc(hHeap,0,Command,BufferSize); } if(basbuf[cp]=='\"'){ Command[i2]=basbuf[cp]; for(cp++,i2++;;cp++,i2++){ if(i2>=BufferSize){ //バッファ領域が足りなくなった場合はバッファを増量する BufferSize+=128; Command=(char *)HeapReAlloc(hHeap,0,Command,BufferSize); } Command[i2]=basbuf[cp]; if(basbuf[cp]=='\"') break; } continue; } if(IsCommandDelimitation(basbuf[cp])){ Command[i2]=0; if(Command[0]==1&&Command[1]==ESC_SUB){ i2=cp; while(!(basbuf[cp]==1&&basbuf[cp+1]==ESC_ENDSUB)){ if(basbuf[cp]=='\0'){ compiler.errorMessenger.Output(22,"Sub",i2); break; } cp++; } if(basbuf[cp+2]=='\0'||basbuf[cp]=='\0') break; cp+=2; i2=-1; continue; } if(Command[0]==1&&Command[1]==ESC_FUNCTION){ i2=cp; while(!(basbuf[cp]==1&&basbuf[cp+1]==ESC_ENDFUNCTION)){ if(basbuf[cp]=='\0'){ compiler.errorMessenger.Output(22,"Function",i2); break; } cp++; } if(basbuf[cp+2]=='\0'||basbuf[cp]=='\0') break; cp+=2; i2=-1; continue; } if(Command[0]==1&&Command[1]==ESC_MACRO){ i2=cp; while(!(basbuf[cp]==1&&basbuf[cp+1]==ESC_ENDMACRO)){ if(basbuf[cp]=='\0'){ compiler.errorMessenger.Output(22,"Macro",i2); break; } cp++; } if(basbuf[cp+2]=='\0'||basbuf[cp]=='\0') break; cp+=2; i2=-1; continue; } if(Command[0]==1&&Command[1]==ESC_TYPE){ i2=cp; while(!(basbuf[cp]==1&&basbuf[cp+1]==ESC_ENDTYPE)){ if(basbuf[cp]=='\0'){ compiler.errorMessenger.Output(22,"Type",i2); break; } cp++; } if(basbuf[cp+2]=='\0'||basbuf[cp]=='\0') break; cp+=2; i2=-1; continue; } if(Command[0]==1&&Command[1]==ESC_CLASS){ i2=cp; while(!(basbuf[cp]==1&&basbuf[cp+1]==ESC_ENDCLASS)){ if(basbuf[cp]=='\0'){ compiler.errorMessenger.Output(22,"Class",i2); break; } cp++; } if(basbuf[cp+2]=='\0'||basbuf[cp]=='\0') break; cp+=2; i2=-1; continue; } if(Command[0]==1&&Command[1]==ESC_INTERFACE){ i2=cp; while(!(basbuf[cp]==1&&basbuf[cp+1]==ESC_ENDINTERFACE)){ if(basbuf[cp]=='\0'){ compiler.errorMessenger.Output(22,"Interface",i2); break; } cp++; } if(basbuf[cp+2]=='\0'||basbuf[cp]=='\0') break; cp+=2; i2=-1; continue; } //DLLのグローバルデータに必要なコマンドだけ if(MAKEWORD(Command[1],Command[0])==COM_DIM) OpcodeDim(Command+2,0); if(basbuf[cp]=='\0') break; i2=-1; continue; } Command[i2]=basbuf[cp]; } HeapDefaultFree(Command); } DWORD CompileBuffer(char Return_Sequence,WORD Return_Command){ extern char *basbuf; extern HANDLE hHeap; int i,i2,i3,i4,BufferSize,ScopeStart; char *Command,temporary[VN_SIZE],*temp2,temp3[32]; DWORD dwRetCode; ScopeStart=cp; dwRetCode=0; BufferSize=128; Command=(char *)HeapAlloc(hHeap,0,BufferSize); for(cp++,i2=0;;cp++,i2++){ if(i2>=BufferSize){ //バッファ領域が足りなくなった場合はバッファを増量する BufferSize+=128; Command=(char *)HeapReAlloc(hHeap,0,Command,BufferSize); } if(basbuf[cp]=='\"'){ Command[i2]=basbuf[cp]; for(cp++,i2++;;cp++,i2++){ if(i2>=BufferSize){ //バッファ領域が足りなくなった場合はバッファを増量する BufferSize+=128; Command=(char *)HeapReAlloc(hHeap,0,Command,BufferSize); } Command[i2]=basbuf[cp]; if(basbuf[cp]=='\"') break; } continue; } if(IsCommandDelimitation(basbuf[cp])){ Command[i2]=0; if(Command[0]==1&&Command[1]==ESC_LINENUM){ for(i=2,i2=0;;i++,i2++){ if(Command[i]==','){ temporary[i2]=0; break; } temporary[i2]=Command[i]; } i3=atoi(temporary); i4=i+1; //Goto先ラベル compiler.codeGenerator.gotoLabels.push_back( GotoLabel( (long)i3, compiler.codeGenerator.GetNativeCodeSize() ) ); //書き込みスケジュール GotoLabelSchedules::iterator it = compiler.codeGenerator.gotoLabelSchedules.begin(); while( it != compiler.codeGenerator.gotoLabelSchedules.end() ) { if( (*it)->GetName().size() == 0 && (*it)->GetLineNum() == i3 ) { compiler.codeGenerator.opfix_JmpPertialSchedule( (*it) ); //詰める it = compiler.codeGenerator.gotoLabelSchedules.erase( it ); } else { it++; } } temp2=(char *)HeapAlloc(hHeap,0,lstrlen(Command+i4)+1); lstrcpy(temp2,Command+i4); lstrcpy(Command,temp2); HeapDefaultFree(temp2); } if(Command[0]==1&& (((Command[1]==ESC_VIRTUAL||Command[1]==ESC_OVERRIDE)&&Command[2]==1&&(Command[3]==ESC_SUB||Command[3]==ESC_FUNCTION))|| Command[1]==ESC_SUB|| Command[1]==ESC_FUNCTION|| Command[1]==ESC_MACRO|| Command[1]==ESC_TYPE|| Command[1]==ESC_CLASS|| Command[1]==ESC_INTERFACE|| Command[1]==ESC_ENUM|| (Command[1]==ESC_CONST&&Command[2]==1&&Command[3]==ESC_ENUM) ) ){ if(Command[1]==ESC_VIRTUAL||Command[1]==ESC_OVERRIDE||Command[1]==ESC_CONST){ GetDefaultNameFromES(Command[3],temporary); } else{ GetDefaultNameFromES(Command[1],temporary); } if(Return_Sequence){ compiler.errorMessenger.Output(12,temporary,cp); break; } if(Command[1]==ESC_CONST) i3=GetEndXXXCommand(Command[3]); else i3=GetEndXXXCommand(Command[1]); for(i2=cp;;cp++){ if(basbuf[cp]==1){ if(basbuf[cp+1]==i3) break; if(Command[1]==ESC_CLASS||Command[1]==ESC_INTERFACE){ //クラス、インターフェイスではSub、Functionの定義を可能にしておく if(basbuf[cp+1]==ESC_MACRO|| basbuf[cp+1]==ESC_TYPE|| basbuf[cp+1]==ESC_CLASS|| basbuf[cp+1]==ESC_INTERFACE|| basbuf[cp+1]==ESC_ENUM){ GetDefaultNameFromES(basbuf[cp+1],temp3); compiler.errorMessenger.Output(12,temp3,cp); } } else{ if(basbuf[cp-1]!='*'&&( basbuf[cp+1]==ESC_VIRTUAL|| basbuf[cp+1]==ESC_OVERRIDE|| basbuf[cp+1]==ESC_SUB|| basbuf[cp+1]==ESC_FUNCTION|| basbuf[cp+1]==ESC_MACRO|| basbuf[cp+1]==ESC_TYPE|| basbuf[cp+1]==ESC_CLASS|| basbuf[cp+1]==ESC_INTERFACE|| basbuf[cp+1]==ESC_ENUM)){ GetDefaultNameFromES(basbuf[cp+1],temp3); compiler.errorMessenger.Output(12,temp3,cp); } } } if(basbuf[cp]=='\0'){ //error //既にエラー発行済みのため、何もせずに抜ける break; } } if(basbuf[cp+2]=='\0'||basbuf[cp]=='\0') break; cp+=2; i2=-1; continue; } if(Command[0]==0x10||Command[0]==0x11){ //Wend、Next、Loopなど if(Return_Command==MAKEWORD(Command[1],Command[0])){ if(Return_Command==COM_NEXT){ //Nextの場合は、パラメータ(省略化)の整合性を判断する必要がある(OpcodeFor関数を参照) extern char szNextVariable[VN_SIZE]; if(Command[2]) lstrcpy(szNextVariable,Command+2); else szNextVariable[0]=0; } break; } } compiler.codeGenerator.NextSourceLine( compiler.GetCurrentRelationalObjectModuleIndexForSource() ); if(Command[0]==1){ if(Return_Sequence==ESC_ENDIF&&Command[1]==ESC_ELSE){ dwRetCode=ESC_ELSE; break; } if(Command[1]==Return_Sequence){ dwRetCode=Command[1]; break; } } if( Command[0] ) { ChangeOpcode(Command); } epi_check(); //コンパイルを中断するとき extern BOOL bStopCompile; if(bStopCompile) return 0; if(basbuf[cp]=='\0'){ switch(Return_Command){ case COM_WEND: compiler.errorMessenger.Output(4,"\"While\" - \"Wend\" ",ScopeStart); break; case COM_NEXT: compiler.errorMessenger.Output(4,"\"For\" - \"Next\" ",ScopeStart); break; case COM_LOOP: compiler.errorMessenger.Output(4,"\"Do\" - \"Loop\" ",ScopeStart); break; } switch(Return_Sequence){ case ESC_ENDSUB: compiler.errorMessenger.Output(4,"\"Sub\" - \"End Sub\" ",ScopeStart); break; case ESC_ENDFUNCTION: compiler.errorMessenger.Output(4,"\"Function\" - \"End Function\" ",ScopeStart); break; case ESC_ENDMACRO: compiler.errorMessenger.Output(4,"\"Macro\" - \"End Macro\" ",ScopeStart); break; case ESC_ENDIF: compiler.errorMessenger.Output(22,"If",ScopeStart); break; } break; } i2=-1; continue; } Command[i2]=basbuf[cp]; } HeapDefaultFree(Command); return dwRetCode; }