#include "stdafx.h" #ifdef _AMD64_ #include "../compiler_x64/opcode.h" #else #include "../compiler_x86/opcode.h" #endif #define OVERLOAD_MIN_LEVEL 0 #define OVERLOAD_MAX_LEVEL 6 #define OVERLOAD_LEVEL0 0 // 型調整なし。厳密に等しい #define OVERLOAD_LEVEL1 1 // 型調整なし。レベル1以上はオブジェクトの場合は派生関係を考慮 #define OVERLOAD_LEVEL2 2 // 型調整なし。整数型/実数型レベルでの同一性チェック(サイズ照合あり) #define OVERLOAD_LEVEL3 3 // 型調整なし。整数型/実数型レベルでの同一性チェック #define OVERLOAD_LEVEL4 4 // 型調整あり。厳密に等しい #define OVERLOAD_LEVEL5 5 // 型調整あり。整数型/実数型レベルでの同一性チェック #define OVERLOAD_LEVEL6 6 // 型調整あり。数値型/クラス型レベルでの同一性チェック ParamImpl::ParamImpl(const char *buffer): returnType() { /////////////////////////// // パラメータ文字列を整理 /////////////////////////// extern HANDLE hHeap; int i,i2,i3; char temporary[VN_SIZE]; i=0; ParmsNum=0; while(1){ if(buffer[i]=='\0') break; for(i2=0;;i2++,i++){ if(buffer[i]=='\"'){ temporary[i2]=buffer[i]; for(i++,i2++;;i++,i2++){ temporary[i2]=buffer[i]; if( buffer[i] == '\0' ) { compiler.errorMessenger.OutputFatalError(); break; } if(buffer[i]=='\"') break; } continue; } if(buffer[i]=='('){ i3=GetStringInPare(temporary+i2,buffer+i); i2+=i3-1; i+=i3-1; continue; } if(buffer[i]=='['){ i3=GetStringInBracket(temporary+i2,buffer+i); i2+=i3-1; i+=i3-1; continue; } if(buffer[i]==','||buffer[i]=='\0'){ temporary[i2]=0; break; } temporary[i2]=buffer[i]; } Parms[ParmsNum]=(char *)HeapAlloc(hHeap,0,lstrlen(temporary)+1); lstrcpy(Parms[ParmsNum],temporary); ParmsNum++; types.push_back( Type() ); if(buffer[i]==',') i++; } } ParamImpl::ParamImpl(const Parameters ¶ms): returnType() { ParmsNum = 0; foreach( Parameter *pParam, params ){ Parms[ParmsNum]=0; ParmsNum++; types.push_back( *pParam ); } } ParamImpl::~ParamImpl(){ int i2; //パラメータ文字列を解放 for(i2=0;i2returnType = returnType; } bool ParamImpl::EvaluateOverloadScore( int level, const Parameters &targetParms, const Type &targetResultType, const Type &leftType, const UserProc &userProc, bool &isErrored ){ //パラメータを識別してオーバーロードを解決 isErrored = false; //パラメータの個数が不一致の場合 int max = (int)targetParms.size(); if( ParmsNum > max ){ // 実引数が駆り引数より多いとき // ※無条件で不一致 return false; } Type argType; for(int i=0;i= ParmsNum ){ // 引数が多いとき if( param.GetInitValue().size() > 0 ){ // 初期値が指定されているパラメータを考慮 return true; } else{ return false; } } if(Parms[i]){ Type nullParam( DEF_NON ); if( !NumOpe_GetType(Parms[i], ( level <= OVERLOAD_LEVEL3 )? nullParam : paramType, argType) ) { isErrored = true; return false; } } else{ argType = types[i]; } if( ( argType.IsObject() && paramType.IsObject() ) || argType.GetBasicType() == paramType.GetBasicType() ) { if( argType.IsStruct() ){ if(argType.GetIndex()!=paramType.GetIndex()){ return false; } } else if( argType.IsObject() ){ if( level == OVERLOAD_LEVEL0 ){ if( !paramType.GetClass().IsEquals( &argType.GetClass() ) ){ return false; } } else{ if( !paramType.GetClass().IsEqualsOrSubClass( &argType.GetClass() ) ){ return false; } } } } else { if( level == OVERLOAD_LEVEL0 || level == OVERLOAD_LEVEL1 || level==OVERLOAD_LEVEL4 ){ return false; } else if( level == OVERLOAD_LEVEL2 ){ if( !(argType.IsWhole() && paramType.IsWhole() && argType.GetBasicSize() == paramType.GetBasicSize() ) ){ // サイズ違い return false; } } else if( level == OVERLOAD_LEVEL3 || level==OVERLOAD_LEVEL5){ if(!( argType.IsWhole()&¶mType.IsWhole()|| argType.IsReal()&¶mType.IsReal() )){ return false; } if( argType.IsPointer() || paramType.IsPointer() ) { // ポインタ型の不整合は認めない return false; } } else if(level==OVERLOAD_LEVEL6){ if(argType.IsObject()||paramType.IsObject()) return false; } } } if( !targetResultType.IsNull() ){ //戻り値も比較対象にする Type temp( targetResultType ); ResolveFormalGenericTypeParameter( temp, leftType, &userProc ); if( !returnType.Equals( temp ) ){ return false; } } return true; } const UserProc *ParamImpl::_OverloadSolution( const char *name, std::vector &subs, const Type &leftType, bool isEnabledReturnType ){ const UserProc *pUserProc = NULL; for( int level=OVERLOAD_MIN_LEVEL; level<=OVERLOAD_MAX_LEVEL; level++ ) { foreach( const UserProc *pTempUserProc, subs ) { bool isErrored = false; bool isHit = false; isHit = EvaluateOverloadScore( level, pTempUserProc->Params(), isEnabledReturnType?pTempUserProc->ReturnType():Type(), leftType, *pTempUserProc, isErrored ); if( isErrored ) { // 照合中にエラーが起きた場合 return NULL; } if( isHit ) { trace_for_overload( "レベル" << level << " ○適合..." << pTempUserProc->_paramStr ); if( pUserProc ){ if( isEnabledReturnType ){ compiler.errorMessenger.Output(52,name,cp); return NULL; } else{ // 戻り値も比較するモードにして再びオーバーロード解決を試みる trace_for_overload( "戻り値も比較するモードに切り替えてオーバーロード解決を試みる" ); return OverloadSolution( name, subs, leftType, true); } } pUserProc = pTempUserProc; } else { trace_for_overload( "レベル" << level << " ×不適合..." << pTempUserProc->_paramStr ); } } if( pUserProc ) break; } if( !pUserProc ){ foreach( const UserProc *pTempUserProc, subs ) { //エラーチェック if(pTempUserProc->Params().size()==this->ParmsNum) { if( pUserProc ) { compiler.errorMessenger.Output(52,name,cp); return NULL; } pUserProc=pTempUserProc; } } } if( !pUserProc ) { compiler.errorMessenger.OutputFatalError(); } return pUserProc; } const UserProc *ParamImpl::OverloadSolution( const char *name, std::vector &subs, const Type &leftType, bool isEnabledReturnType ){ trace_for_overload( "" ); trace_for_overload( "■■■■■■■■■■■■■■■■■■" ); trace_for_overload( "■■■ オーバーロード解決(" << name << ")" ); const UserProc *result = _OverloadSolution( name, subs, leftType, isEnabledReturnType ); trace_for_overload( "■■■ ここまで" ); trace_for_overload( "■■■■■■■■■■■■■■■■■■" ); trace_for_overload( "" ); return result; } void ParamImpl::ApplyDefaultParameters( const Parameters ¶ms ){ if( ParmsNum == (int)params.size() ){ // デフォルト引数の適用が不必要なとき return; } while( ParmsNum < (int)params.size() ){ Parameter ¶m = *params[ParmsNum]; Parms[ParmsNum]=(char *)HeapAlloc(hHeap,0,param.GetInitValue().size() + 1 ); lstrcpy(Parms[ParmsNum],param.GetInitValue().c_str() ); ParmsNum++; types.push_back( Type() ); } } bool ParamImpl::ErrorCheck( const std::string &procName, const Parameters ¶ms, int SecondParmNum ){ if( SecondParmNum == -1 ) SecondParmNum = (int)params.size(); if(ParmsNum>(int)params.size()){ if( params.size() == 0 || params[params.size()-1]->GetBasicType()!=DEF_ELLIPSE ){ //パラメータが多すぎるとき compiler.errorMessenger.Output(10,procName,cp); return false; } } else if(ParmsNum<(int)params.size()){ if(ParmsNumGetBasicType()==DEF_ELLIPSE){ return true; } //パラメータが少なすぎるとき compiler.errorMessenger.Output(10,procName,cp); return false; } //省略パラメータに "0" を指定する while( ParmsNum < (int)params.size() ) { extern HANDLE hHeap; char temporary[64]; if(params[ParmsNum]->IsRef() == false) lstrcpy(temporary,"0"); else sprintf(temporary,"%c%c0",1,ESC_BYVAL); Parms[ParmsNum]=(char *)HeapAlloc(hHeap,0,lstrlen(temporary)+1); lstrcpy(Parms[ParmsNum],temporary); ParmsNum++; types.push_back( Type() ); } } return true; } void ParamImpl::MacroParameterSupport( const Parameters ¶ms ){ for(int i=0;iIsRef() == false ) lstrcpy(temporary,"0"); else sprintf(temporary,"%c%c0",1,ESC_BYVAL); HeapDefaultFree(Parms[i]); Parms[i]=(char *)HeapAlloc(hHeap,0,lstrlen(temporary)+1); lstrcpy(Parms[i],temporary); } } }