#include "common.h" #ifdef _AMD64_ #include "../BasicCompiler64/opcode.h" #else #include "../BasicCompiler32/opcode.h" #endif #define OVERLOAD_MIN_LEVEL 0 #define OVERLOAD_MAX_LEVEL 4 #define OVERLOAD_LEVEL0 0 // 型調整なし。厳密に等しい #define OVERLOAD_LEVEL1 1 // 型調整なし。整数型/実数型レベルでの同一性チェック #define OVERLOAD_LEVEL2 2 // 型調整あり。厳密に等しい #define OVERLOAD_LEVEL3 3 // 型調整あり。整数型/実数型レベルでの同一性チェック #define OVERLOAD_LEVEL4 4 // 型調整あり。数値型/クラス型レベルでの同一性チェック 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]=='\"') 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::_overload_check( int level, const Parameters &targetParms, const Type &targetResultType ){ //パラメータを識別してオーバーロードを解決 //パラメータの個数が不一致の場合 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 ); NumOpe_GetType(Parms[i], (level==OVERLOAD_LEVEL0 || level == OVERLOAD_LEVEL1)? nullParam : param, argType); } else{ argType = types[i]; } if(argType.GetBasicType()!=param.GetBasicType()){ if( level == OVERLOAD_LEVEL0 || level==OVERLOAD_LEVEL2 ){ return false; } else if( level == OVERLOAD_LEVEL1 || level==OVERLOAD_LEVEL3){ if(!( argType.IsWhole()&¶m.IsWhole()|| argType.IsReal()&¶m.IsReal() )){ return false; } } else if(level==OVERLOAD_LEVEL4){ if(argType.IsObject()||param.IsObject()) return false; } } else{ //if(NATURAL_TYPE(argType.GetBasicType())==DEF_OBJECT || NATURAL_TYPE(argType.GetBasicType())==DEF_STRUCT){ if( NATURAL_TYPE(argType.GetBasicType())==DEF_STRUCT){ if(argType.GetIndex()!=param.GetIndex()){ return false; } } else if( NATURAL_TYPE(argType.GetBasicType())==DEF_OBJECT ){ if( !param.GetClass().IsEqualsOrSubClass( &argType.GetClass() ) ){ return false; } } } } if( !targetResultType.IsNull() ){ //戻り値も比較対象にする if( !returnType.Equals( targetResultType ) ){ return false; } } return true; } UserProc *ParamImpl::OverloadSolutionWithReturnType( const char *name, std::vector &subs ){ int sw=0; UserProc *pUserProc = NULL; for( int level=OVERLOAD_MIN_LEVEL; level<=OVERLOAD_MAX_LEVEL; level++ ){ foreach( UserProc *pTempUserProc, subs ){ //エラーチェック if(_overload_check( level, pTempUserProc->Params(), pTempUserProc->ReturnType() )){ if(sw){ SetError(52,name,cp); return 0; } sw=1; pUserProc = pTempUserProc; break; } } if( sw ) break; } if(!sw){ SetError(52,name,cp); return 0; } return pUserProc; } UserProc *ParamImpl::OverloadSolution( const char *name, std::vector &subs ){ int sw=0; UserProc *pUserProc; pUserProc=0; for( int level=OVERLOAD_MIN_LEVEL; level<=OVERLOAD_MAX_LEVEL; level++ ){ foreach( UserProc *pTempUserProc, subs ){ //エラーチェック if(_overload_check( level, pTempUserProc->Params(), Type() )){ if(sw){ return OverloadSolutionWithReturnType(name,subs); } sw=1; pUserProc = pTempUserProc; } } if( sw ) break; } if(!sw){ foreach( UserProc *pTempUserProc, subs ){ //エラーチェック if(pTempUserProc->Params().size()==this->ParmsNum){ if(sw){ sw=0; break; } sw=1; pUserProc=pTempUserProc; } } } if(!sw){ SetError(52,name,cp); return 0; } return pUserProc; } 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++; } } bool ParamImpl::ErrorCheck( const string &procName, const Parameters ¶ms, int SecondParmNum ){ if( SecondParmNum == -1 ) SecondParmNum = (int)params.size(); if(ParmsNum>(int)params.size()){ if(params[params.size()-1]->GetBasicType()!=DEF_ELLIPSE){ //パラメータが多すぎるとき SetError(10,procName,cp); return false; } } else if(ParmsNum<(int)params.size()){ if(ParmsNumGetBasicType()==DEF_ELLIPSE){ return true; } //パラメータが少なすぎるとき SetError(10,procName,cp); return false; } //省略パラメータに "0" を指定する for(;ParmsNum < (int)params.size();ParmsNum++){ 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); } } 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); } } }