#include "../BasicCompiler_Common/common.h" #ifdef _AMD64_ #include "../BasicCompiler64/opcode.h" #else #include "../BasicCompiler32/opcode.h" #endif int GetCallProcName(char *buffer,char *name){ int i2,i3,IsStr=0; for(i2=0;;i2++){ if(buffer[i2]=='\"') IsStr^=1; if(IsDBCSLeadByte(buffer[i2])){ name[i2]=buffer[i2]; i2++; name[i2]=buffer[i2]; continue; } if(buffer[i2]=='['&&IsStr==0){ i3=GetStringInBracket(name+i2,buffer+i2); i2+=i3-1; continue; } if(buffer[i2]=='('&&IsStr==0){ name[i2]=0; break; } if(buffer[i2]=='='&&IsStr==0){ name[i2]=0; break; } name[i2]=buffer[i2]; if(buffer[i2]=='\0') break; } return i2; } int GetProc(char *name,void **ppInfo){ //ユーザー定義関数 *ppInfo=(void *)GetSubHash(name); if(*ppInfo) return PROC_DEFAULT; //DLL関数 *ppInfo=(void *)GetDeclareHash(name); if(*ppInfo) return PROC_DLL; //コンパイラ埋め込み型 *ppInfo=(void *)(_int64)GetFunctionFromName(name); if(*ppInfo) return PROC_BUILTIN; //関数ポインタ Type type; if( !GetVarType( name, type, false ) ){ return 0; } if( type.IsProcPtr() ){ return PROC_PTR; } return 0; } void SplitObjectName(const char *name,char *ObjectName,int *pRefType){ int i4; for(i4=lstrlen(name)-1;i4>=0;i4--){ if(name[i4]=='.'||(name[i4]==1&&name[i4+1]==ESC_PSMEM)) break; } if(i4==-1) ObjectName[0]=0; else{ //参照タイプを判別 if(name[i4]=='.') *pRefType=DEF_OBJECT; else *pRefType=DEF_PTR_OBJECT; if(i4==0) GetWithName(ObjectName); else{ memcpy(ObjectName,name,i4); ObjectName[i4]=0; } } } bool SplitMemberName( const char *desc, char *object, char *member, CClass::RefType &refType ){ int lastIndex = -1; for( int i=0; desc[i]; i++ ){ if( desc[i] == '(' ){ i=JumpStringInPare(desc,i+1); continue; } else if( desc[i] == '[' ){ i=JumpStringInBracket(desc,i+1); continue; } else if(desc[i]=='.'||(desc[i]==1&&desc[i+1]==ESC_PSMEM)){ lastIndex = i; } } if( lastIndex == -1 ){ lstrcpy( member, desc ); return false; } if(desc[lastIndex]=='.'){ lstrcpy(member,desc+lastIndex+1); refType = CClass::Dot; } else{ lstrcpy(member,desc+lastIndex+2); refType = CClass::Pointer; } if( object ){ lstrcpy( object, desc ); object[lastIndex]=0; } return true; } bool SplitMemberName( const char *desc, char *object, char *member ){ CClass::RefType dummyRefType; return SplitMemberName( desc, object, member, dummyRefType ); } bool CallProc( int kind, const void *pProc, const char *fullCallName, const char *lpszParms, Type &resultType, bool isCallOn ){ //GetSubHash内でエラー提示が行われた場合 if(pProc==(Procedure *)-1){ return false; } if(kind==PROC_DEFAULT){ ///////////////////// // ユーザー定義関数 ///////////////////// UserProc *pUserProc = (UserProc *)pProc; //オブジェクト名を取得 char ObjectName[VN_SIZE]; int RefType; SplitObjectName(fullCallName,ObjectName,&RefType); //////////////////////// // オーバーロードを解決 //////////////////////// std::vector subs; GetOverloadSubHash(fullCallName,subs); if(subs.size()){ //オーバーロードを解決 pUserProc=OverloadSolutionWithStrParam(fullCallName,subs,lpszParms,ObjectName); if(!pUserProc){ return false; } } resultType = pUserProc->ReturnType(); if( isCallOn ){ if( !Opcode_CallProc(lpszParms,pUserProc,0,ObjectName,RefType) ){ return false; } } } else if(kind==PROC_DLL){ ///////////////////////// // DLL関数 ///////////////////////// DllProc *pDllProc = (DllProc *)pProc; resultType = pDllProc->ReturnType(); if( isCallOn ){ if( !Opcode_CallDllProc(lpszParms,pDllProc) ){ return false; } } } else if(kind==PROC_BUILTIN){ ///////////////////////// // 組み込み関数 ///////////////////////// int FuncId = (int)(_int64)pProc; if( !Opcode_CallFunc( lpszParms, FuncId, resultType, isCallOn ) ){ return false; } } else if(kind==PROC_PTR){ ///////////////// // 関数ポインタ ///////////////// Type type; GetVarType(fullCallName,type,false); ProcPointer *pProcPtr = Smoothie::Meta::procPointers[type.GetIndex()]; resultType = pProcPtr->ReturnType(); if( isCallOn ){ if( !Opcode_CallProcPtr(fullCallName,lpszParms,pProcPtr) ){ return false; } } } else{ return false; } return true; } bool CallPropertyMethod( const char *variable, const char *rightSide, Type &resultType){ //プロパティ用のメソッドを呼び出す //配列要素を取得 char VarName[VN_SIZE],ArrayElements[VN_SIZE]; GetArrayElement(variable,VarName,ArrayElements); //オブジェクト名を取得 char ObjectName[VN_SIZE]; int RefType; SplitObjectName(VarName,ObjectName,&RefType); //オーバーロード用の関数リストを作成 std::vector subs; GetOverloadSubHash(VarName,subs); if(subs.size()==0){ return false; } //パラメータを整備 char *Parameter; Parameter=(char *)HeapAlloc(hHeap,0,lstrlen(ArrayElements)+lstrlen(rightSide)+32); lstrcpy(Parameter,ArrayElements); if(rightSide){ if(Parameter[0]&&rightSide[0]) lstrcat(Parameter,","); lstrcat(Parameter,rightSide); } //オーバーロードを解決 UserProc *pUserProc; pUserProc=OverloadSolutionWithStrParam(VarName,subs,Parameter,ObjectName); if(pUserProc){ //呼び出し Opcode_CallProc(Parameter,pUserProc,0,ObjectName,RefType); resultType = pUserProc->ReturnType(); } HeapDefaultFree(Parameter); return true; } bool GetReturnTypeOfPropertyMethod( const char *variable, const char *rightSide, Type &resultType ){ //プロパティ用のメソッドを呼び出す //配列要素を取得 char VarName[VN_SIZE],ArrayElements[VN_SIZE]; GetArrayElement(variable,VarName,ArrayElements); //オブジェクト名を取得 char ObjectName[VN_SIZE]; int RefType; SplitObjectName(VarName,ObjectName,&RefType); //オーバーロード用の関数リストを作成 std::vector subs; GetOverloadSubHash(VarName,subs); if(subs.size()==0){ return 0; } //パラメータを整備 char *Parameter; Parameter=(char *)HeapAlloc(hHeap,0,lstrlen(ArrayElements)+lstrlen(rightSide)+32); lstrcpy(Parameter,ArrayElements); if(rightSide){ if(Parameter[0]&&rightSide[0]) lstrcat(Parameter,","); lstrcat(Parameter,rightSide); } //オーバーロードを解決 UserProc *pUserProc; pUserProc=OverloadSolutionWithStrParam(VarName,subs,Parameter,ObjectName); if(pUserProc){ resultType = pUserProc->ReturnType(); } return 1; } //インデクサ(getter)の戻り値を取得 bool GetReturnTypeOfIndexerGetterProc( const CClass &objClass, Type &resultType ){ vector subs; objClass.GetMethods().Enum( CALC_ARRAY_GET, subs ); if( subs.size() == 0 ){ return false; } resultType = subs[0]->ReturnType(); return true; } void AddDeclareData(const NamespaceScopes &namespaceScopes, char *buffer,int nowLine){ extern HANDLE hHeap; int i2; int i=0; //Sub/Function Procedure::Kind kind = Procedure::Sub; if(buffer[i]==ESC_SUB){ } else if(buffer[i]==ESC_FUNCTION){ kind = Procedure::Function; } else{ SetError(1,NULL,nowLine); return; } i++; //プロシージャ名 char procName[VN_SIZE]; bool isCdecl = false; for(i2=0;;i++,i2++){ if(buffer[i]==1&&buffer[i+1]==ESC_CDECL){ isCdecl = true; i+=2; procName[i2]=0; break; } if(buffer[i]==','){ procName[i2]=0; break; } if(buffer[i]=='\0'){ SetError(1,NULL,nowLine); return; } procName[i2]=buffer[i]; } i++; //ユーザー定義関数との重複チェック if(GetSubHash(procName)){ SetError(15,procName,nowLine); return; } //ライブラリ char dllFileName[MAX_PATH]; i = GetOneParameter( buffer, i, dllFileName ); Type resultType; _int64 i64data; if( !StaticCalculation( true, dllFileName, 0, &i64data, resultType ) ){ return; } if( resultType.GetBasicType() != typeOfPtrChar ){ SetError(1,NULL,nowLine); return; } lstrcpy( dllFileName, (char *)i64data ); CharUpper(dllFileName); if(!strstr(dllFileName,".")){ lstrcat(dllFileName,".DLL"); if(lstrlen(dllFileName)>=16){ SetError(7,NULL,nowLine); return; } } //エイリアス char alias[VN_SIZE]; i = GetOneParameter( buffer, i, alias ); if( alias[0] ){ if( !StaticCalculation( true, alias, 0, &i64data, resultType ) ){ return; } if( resultType.GetBasicType() != typeOfPtrChar ){ SetError(1,NULL,nowLine); return; } lstrcpy( alias, (char *)i64data ); } else{ //省略されたときは関数名 lstrcpy( alias, procName ); } // オブジェクトを生成 DllProc *pDllProc = new DllProc( namespaceScopes, procName, kind, isCdecl, dllFileName, alias ); // パラメータを解析 // ※第1パラメータにに指定するデータの例:"( s As String ) As String" pDllProc->SetParamsAndReturnType( buffer + i, nowLine ); // パラメータのエラーチェック foreach( const Parameter *pParam, pDllProc->Params() ){ if( pParam->IsObject() ){ SetError(25,pParam->GetVarName(),nowLine); } if( !pParam->IsRef() ){ if( pParam->IsStruct() ){ SetError(28,pParam->GetVarName(),nowLine); } } } //戻り値のエラーチェック if( pDllProc->IsFunction() ){ // Function定義 if( pDllProc->ReturnType().IsObject() ){ // DLL関数ではオブジェクトを戻り値にできない SetError(40,pDllProc->GetName(),nowLine); } } ///////////////////////////////// // 格納位置を計算してppDeclareHashにセット ///////////////////////////////// //ハッシュ値を取得 int key; key=hash_default(procName); extern DllProc **ppDeclareHash; if(ppDeclareHash[key]){ DllProc *pTempProc = ppDeclareHash[key]; while(1){ if( pTempProc->IsEqualSymbol( pDllProc->GetNamespaceScopes(), pDllProc->GetName() ) ){ //重複エラー SetError(15,procName,nowLine); return; } if(pTempProc->pNextData==0){ pTempProc->pNextData=pDllProc; break; } pTempProc=pTempProc->pNextData; } pTempProc=pTempProc->pNextData; } else{ ppDeclareHash[key]=pDllProc; } } GlobalProc *AddSubData( const NamespaceScopes &namespaceScopes, const NamespaceScopesCollection &importedNamespaces, char *buffer,int nowLine,bool isVirtual,CClass *pobj_c, bool isStatic){ int i2,i3; char temporary[8192]; int i=1; Procedure::Kind kind = Procedure::Sub; bool isMacro = false; if(buffer[i]==ESC_FUNCTION) kind = Procedure::Function; if(buffer[i]==ESC_MACRO){ isMacro = true; } i++; bool isCdecl = false; bool isExport = false; while(1){ if(buffer[i]==1&&buffer[i+1]==ESC_CDECL&& isCdecl == false ){ isCdecl = true; i+=2; } else if(buffer[i]==1&&buffer[i+1]==ESC_EXPORT&& isExport == false ){ isExport = true; i+=2; } else break; } i2=0; if(buffer[i]==1&&buffer[i+1]==ESC_OPERATOR){ if(!pobj_c){ SetError(126,NULL,nowLine); return 0; } //オペレータの場合 temporary[i2++]=buffer[i++]; temporary[i2++]=buffer[i++]; int iCalcId; if(buffer[i]=='='&&buffer[i+1]=='='){ iCalcId=CALC_EQUAL; i3=2; } else if(buffer[i]=='='){ iCalcId=CALC_SUBSITUATION; i3=1; } else if(buffer[i]=='('){ iCalcId=CALC_AS; i3=0; } else if(buffer[i]=='['&&buffer[i+1]==']'&&buffer[i+2]=='='){ iCalcId=CALC_ARRAY_SET; i3=3; } else if(buffer[i]=='['&&buffer[i+1]==']'){ iCalcId=CALC_ARRAY_GET; i3=2; } else{ iCalcId=GetCalcId(buffer+i,&i3); i3++; } if(!iCalcId){ SetError(1,NULL,nowLine); return 0; } temporary[i2++]=iCalcId; temporary[i2]=0; i+=i3; } else{ if(pobj_c){ //クラスメンバの場合、デストラクタには~が付くことを考慮 if(buffer[i]=='~'){ temporary[i2]='~'; i++; i2++; } } for(;;i++,i2++){ if(!IsVariableChar(buffer[i])){ temporary[i2]=0; break; } temporary[i2]=buffer[i]; } } if( isMacro ){ //大文字に変換 CharUpper(temporary); //マクロ関数の場合は名前リストに追加 extern char **ppMacroNames; extern int MacroNum; ppMacroNames=(char **)HeapReAlloc(hHeap,0,ppMacroNames,(MacroNum+1)*sizeof(char *)); ppMacroNames[MacroNum]=(char *)HeapAlloc(hHeap,0,lstrlen(temporary)+1); lstrcpy(ppMacroNames[MacroNum],temporary); MacroNum++; } if(!pobj_c){ //クラスメンバ以外の場合のみ //重複チェック if(GetDeclareHash(temporary)){ SetError(15,temporary,nowLine); return 0; } } extern int SubNum; SubNum++; GlobalProc *pUserProc = new GlobalProc( namespaceScopes, importedNamespaces, temporary, kind, isMacro, isCdecl, isExport ); pUserProc->SetParentClass( pobj_c ); if( Smoothie::isFullCompile ){ // すべての関数・メソッドをコンパイルする pUserProc->Using(); } //ID static int id_base=0; pUserProc->id = (id_base++); if(isExport){ pUserProc->Using(); } // パラメータを解析 // ※第1パラメータにに指定するデータの例:"( s As String ) As String" pUserProc->SetParamsAndReturnType( buffer + i, nowLine, isStatic ); pUserProc->_paramStr = buffer + i; ///////////////////////////////// // ハッシュデータに追加 ///////////////////////////////// int key; key=hash_default(pUserProc->GetName().c_str()); extern GlobalProc **ppSubHash; if(ppSubHash[key]){ GlobalProc *psi2; psi2=ppSubHash[key]; while(1){ if(pobj_c==psi2->GetParentClassPtr()){ //重複エラーチェックを行う if( pUserProc->IsEqualSymbol( *psi2 ) ){ if( psi2->Params().Equals( pUserProc->Params() ) ){ SetError(15,pUserProc->GetName().c_str(),nowLine); return 0; } } } if(psi2->pNextData==0) break; psi2=psi2->pNextData; } psi2->pNextData=pUserProc; } else{ ppSubHash[key]=pUserProc; } return pUserProc; } void GetSubInfo(void){ //サブルーチン情報を取得 extern HANDLE hHeap; extern char *basbuf; int i,i2,i3; char temporary[8192]; //Declare(DLL関数)情報を初期化 extern DllProc **ppDeclareHash; ppDeclareHash=(DllProc **)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,MAX_HASH*sizeof(DllProc *)); //サブルーチン(ユーザー定義)情報を初期化 extern GlobalProc **ppSubHash; extern int SubNum; ppSubHash=(GlobalProc **)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,MAX_HASH*sizeof(GlobalProc *)); SubNum=0; //マクロ関数の名前リストを初期化 extern char **ppMacroNames; extern int MacroNum; ppMacroNames=(char **)HeapAlloc(hHeap,0,1); MacroNum=0; // 名前空間管理 NamespaceScopes &namespaceScopes = Smoothie::Lexical::liveingNamespaceScopes; namespaceScopes.clear(); // Importsされた名前空間の管理 NamespaceScopesCollection &importedNamespaces = Smoothie::Meta::importedNamespaces; importedNamespaces.clear(); i=-1; while(1){ i++; if(basbuf[i]==1&&(basbuf[i+1]==ESC_CLASS||basbuf[i+1]==ESC_INTERFACE)){ /* Class 〜 End Class Interface 〜 End Interface を飛び越す */ i3=GetEndXXXCommand(basbuf[i+1]); for(i+=2,i2=0;;i++,i2++){ if(basbuf[i]=='\0') break; if(basbuf[i]==1&&basbuf[i+1]==(char)i3){ i++; break; } } if(basbuf[i]=='\0') break; continue; } if( basbuf[i] == 1 && basbuf[i+1] == ESC_NAMESPACE ){ for(i+=2,i2=0;;i2++,i++){ if( IsCommandDelimitation( basbuf[i] ) ){ temporary[i2]=0; break; } temporary[i2]=basbuf[i]; } namespaceScopes.push_back( temporary ); continue; } else if( basbuf[i] == 1 && basbuf[i+1] == ESC_ENDNAMESPACE ){ if( namespaceScopes.size() <= 0 ){ SetError(12, "End Namespace", i ); } else{ namespaceScopes.pop_back(); } i += 2; continue; } else if( basbuf[i] == 1 && basbuf[i+1] == ESC_IMPORTS ){ for(i+=2,i2=0;;i2++,i++){ if( IsCommandDelimitation( basbuf[i] ) ){ temporary[i2]=0; break; } temporary[i2]=basbuf[i]; } importedNamespaces.Imports( temporary ); continue; } else if( basbuf[i] == 1 && basbuf[i+1] == ESC_CLEARNAMESPACEIMPORTED ){ importedNamespaces.clear(); continue; } if(basbuf[i]==1&&basbuf[i+1]==ESC_DECLARE){ for(i+=2,i2=0;;i2++,i++){ if(basbuf[i]=='\n'){ temporary[i2]=0; break; } temporary[i2]=basbuf[i]; if(basbuf[i]=='\0') break; } AddDeclareData(namespaceScopes,temporary,i); continue; } if(basbuf[i]==1&&(basbuf[i+1]==ESC_SUB||basbuf[i+1]==ESC_FUNCTION||basbuf[i+1]==ESC_MACRO)){ char statementChar = basbuf[i+1]; for(i2=0;;i2++,i++){ if(IsCommandDelimitation(basbuf[i])){ temporary[i2]=0; break; } temporary[i2]=basbuf[i]; if(basbuf[i]=='\0') break; } AddSubData(namespaceScopes, importedNamespaces, temporary,i,0,0); /* Sub 〜 End Sub Function 〜 End Function Macro 〜 End Macro を飛び越す */ char endStatementChar = GetEndXXXCommand( statementChar ); for(i2=0;;i++,i2++){ if( basbuf[i] == '\0' ) break; if( basbuf[i] == 1 && basbuf[i+1] == endStatementChar ){ i++; break; } } if(basbuf[i]=='\0') break; continue; } //次の行 for(;;i++){ if(IsCommandDelimitation(basbuf[i])) break; } if(basbuf[i]=='\0') break; } //////////// // 特殊関数 //////////// namespaceScopes.clear(); importedNamespaces.clear(); sprintf(temporary,"%c%c_allrem()",1,ESC_SUB); AddSubData( namespaceScopes, importedNamespaces, temporary,0,0,0); sprintf(temporary,"%c%c_aullrem()",1,ESC_SUB); AddSubData( namespaceScopes, importedNamespaces, temporary,0,0,0); sprintf(temporary,"%c%c_allmul()",1,ESC_SUB); AddSubData( namespaceScopes, importedNamespaces, temporary,0,0,0); sprintf(temporary,"%c%c_alldiv()",1,ESC_SUB); AddSubData( namespaceScopes, importedNamespaces, temporary,0,0,0); sprintf(temporary,"%c%c_aulldiv()",1,ESC_SUB); AddSubData( namespaceScopes, importedNamespaces, temporary,0,0,0); sprintf(temporary,"%c%c_allshl()",1,ESC_SUB); AddSubData( namespaceScopes, importedNamespaces, temporary,0,0,0); sprintf(temporary,"%c%c_allshr()",1,ESC_SUB); AddSubData( namespaceScopes, importedNamespaces, temporary,0,0,0); sprintf(temporary,"%c%c_aullshr()",1,ESC_SUB); AddSubData( namespaceScopes, importedNamespaces, temporary,0,0,0); sprintf(temporary,"%c%c_System_InitStaticLocalVariables()",1,ESC_SUB); AddSubData( namespaceScopes, importedNamespaces, temporary,0,0,0); } void Delete_si(GlobalProc *pUserProc){ if(pUserProc->pNextData) Delete_si(pUserProc->pNextData); delete pUserProc; } void DeleteSubInfo(GlobalProc **ppSubHash,char **ppMacroNames,int MacroNum){ //サブルーチン情報のメモリ解放 int i; for(i=0;ipNextData) Delete_di(pDllProc->pNextData); delete pDllProc; } void DeleteDeclareInfo(void){ //DLL情報を解放 extern DllProc **ppDeclareHash; int i; for(i=0;iSetParamsAndReturnType( paramStr.c_str(), nowLine ); Smoothie::Meta::procPointers.push_back( pProcPointer ); return (int)Smoothie::Meta::procPointers.size()-1; } void DeleteProcPtrInfo(void){ BOOST_FOREACH( ProcPointer *pProcPointer, Smoothie::Meta::procPointers ){ delete pProcPointer; } Smoothie::Meta::procPointers.clear(); } bool IsNeedProcCompile(){ for(int i2=0;i2IsUsing() && pUserProc->IsCompiled() == false ){ return true; } pUserProc=pUserProc->pNextData; } } return false; }