source: dev/trunk/ab5.0/abdev/BasicCompiler_Common/ParamImpl.cpp @ 673

Last change on this file since 673 was 673, checked in by dai_9181, 15 years ago

・オーバーロード解決時、戻り値に型パラメータだった場合に型解決されずに、正しいオーバーロード解決が行われない不具合を修正。
・演算子メソッドの戻り値が型パラメータだったとき、型解決が行われない不具合を修正。

File size: 9.0 KB
RevLine 
[206]1#include "stdafx.h"
2
[52]3#ifdef _AMD64_
[485]4#include "../compiler_x64/opcode.h"
[52]5#else
[484]6#include "../compiler_x86/opcode.h"
[52]7#endif
8
[78]9#define OVERLOAD_MIN_LEVEL 0
[111]10#define OVERLOAD_MAX_LEVEL 6
[78]11#define OVERLOAD_LEVEL0 0       // 型調整なし。厳密に等しい
[90]12#define OVERLOAD_LEVEL1 1       // 型調整なし。レベル1以上はオブジェクトの場合は派生関係を考慮
[111]13#define OVERLOAD_LEVEL2 2       // 型調整なし。整数型/実数型レベルでの同一性チェック(サイズ照合あり)
14#define OVERLOAD_LEVEL3 3       // 型調整なし。整数型/実数型レベルでの同一性チェック
15#define OVERLOAD_LEVEL4 4       // 型調整あり。厳密に等しい
16#define OVERLOAD_LEVEL5 5       // 型調整あり。整数型/実数型レベルでの同一性チェック
17#define OVERLOAD_LEVEL6 6       // 型調整あり。数値型/クラス型レベルでの同一性チェック
[78]18
[75]19ParamImpl::ParamImpl(const char *buffer):
20    returnType()
21{
[52]22    ///////////////////////////
23    // パラメータ文字列を整理
24    ///////////////////////////
25
26    extern HANDLE hHeap;
27    int i,i2,i3;
28    char temporary[VN_SIZE];
29
30    i=0;
31    ParmsNum=0;
32    while(1){
33        if(buffer[i]=='\0') break;
34
35        for(i2=0;;i2++,i++){
36            if(buffer[i]=='\"'){
37                temporary[i2]=buffer[i];
38                for(i++,i2++;;i++,i2++){
39                    temporary[i2]=buffer[i];
[319]40                    if( buffer[i] == '\0' )
41                    {
[465]42                        compiler.errorMessenger.OutputFatalError();
[319]43                        break;
44                    }
[52]45                    if(buffer[i]=='\"') break;
46                }
47                continue;
48            }
49
50            if(buffer[i]=='('){
51                i3=GetStringInPare(temporary+i2,buffer+i);
52                i2+=i3-1;
53                i+=i3-1;
54                continue;
55            }
56            if(buffer[i]=='['){
57                i3=GetStringInBracket(temporary+i2,buffer+i);
58                i2+=i3-1;
59                i+=i3-1;
60                continue;
61            }
62
63            if(buffer[i]==','||buffer[i]=='\0'){
64                temporary[i2]=0;
65                break;
66            }
67            temporary[i2]=buffer[i];
68        }
69
70        Parms[ParmsNum]=(char *)HeapAlloc(hHeap,0,lstrlen(temporary)+1);
71        lstrcpy(Parms[ParmsNum],temporary);
72        ParmsNum++;
73
[75]74        types.push_back( Type() );
75
[52]76        if(buffer[i]==',') i++;
77    }
78}
[75]79ParamImpl::ParamImpl(const Parameters &params):
80    returnType()
81{
82    ParmsNum = 0;
[182]83    BOOST_FOREACH( Parameter *pParam, params ){
[75]84        Parms[ParmsNum]=0;
85        ParmsNum++;
[52]86
[75]87        types.push_back( *pParam );
[73]88    }
89}
[71]90ParamImpl::~ParamImpl(){
[52]91    int i2;
92
93    //パラメータ文字列を解放
94    for(i2=0;i2<ParmsNum;i2++){
95        if(Parms[i2]==(char *)-1) continue;
96
97        if(Parms[i2]) HeapDefaultFree(Parms[i2]);
98    }
99}
100
[75]101void ParamImpl::SetReturnType( const Type &returnType ){
102    this->returnType = returnType;
[52]103}
104
[424]105bool ParamImpl::EvaluateOverloadScore( int level, const Parameters &targetParms, const Type &targetResultType, const Type &leftType, const UserProc &userProc, bool &isErrored ){
[52]106    //パラメータを識別してオーバーロードを解決
107
[364]108    isErrored = false;
109
[52]110    //パラメータの個数が不一致の場合
[75]111    int max = (int)targetParms.size();
[77]112
113    if( ParmsNum > max ){
114        // 実引数が駆り引数より多いとき
115        // ※無条件で不一致
[75]116        return false;
117    }
[52]118
[73]119    Type argType;
120    for(int i=0;i<max;i++){
[75]121        Parameter &param = *targetParms[i];
[73]122
[424]123        Type paramType( param );
124        ResolveFormalGenericTypeParameter( paramType, leftType, &userProc );
125
[77]126        if( i >= ParmsNum ){
127            // 引数が多いとき
128            if( param.GetInitValue().size() > 0 ){
129                // 初期値が指定されているパラメータを考慮
130                return true;
131            }
132            else{
133                return false;
134            }
135        }
136
[52]137        if(Parms[i]){
[73]138            Type nullParam( DEF_NON );
139
[364]140            if( !NumOpe_GetType(Parms[i],
[424]141                ( level <= OVERLOAD_LEVEL3 )? nullParam : paramType,
[364]142                argType) )
143            {
144                isErrored = true;
145                return false;
146            }
[52]147        }
148        else{
[75]149            argType = types[i];
[52]150        }
151
[424]152        if( ( argType.IsObject() && paramType.IsObject() ) || argType.GetBasicType() == paramType.GetBasicType() )
153        {
154            if( argType.IsStruct() ){
155                if(argType.GetIndex()!=paramType.GetIndex()){
156                    return false;
157                }
158            }
159            else if( argType.IsObject() ){
160                if( level == OVERLOAD_LEVEL0 ){
161                    if( !paramType.GetClass().IsEquals( &argType.GetClass() ) ){
162                        return false;
163                    }
164                }
165                else{
166                    if( !paramType.GetClass().IsEqualsOrSubClass( &argType.GetClass() ) ){
167                        return false;
168                    }
169                }
170            }
171        }
172        else
173        {
[111]174            if( level == OVERLOAD_LEVEL0 || level == OVERLOAD_LEVEL1 || level==OVERLOAD_LEVEL4 ){
[75]175                return false;
[52]176            }
[111]177            else if( level == OVERLOAD_LEVEL2 ){
[424]178                if( !(argType.IsWhole() && paramType.IsWhole() && argType.GetBasicSize() == paramType.GetBasicSize() ) ){
[111]179                    // サイズ違い
180                    return false;
181                }
182            }
183            else if( level == OVERLOAD_LEVEL3 || level==OVERLOAD_LEVEL5){
[52]184                if(!(
[424]185                    argType.IsWhole()&&paramType.IsWhole()||
186                    argType.IsReal()&&paramType.IsReal()
[75]187                    )){
188                        return false;
189                }
[424]190                if( argType.IsPointer() || paramType.IsPointer() )
[140]191                {
192                    // ポインタ型の不整合は認めない
193                    return false;
194                }
[52]195            }
[111]196            else if(level==OVERLOAD_LEVEL6){
[424]197                if(argType.IsObject()||paramType.IsObject()) return false;
[52]198            }
199        }
200    }
201
[75]202    if( !targetResultType.IsNull() ){
[52]203        //戻り値も比較対象にする
[673]204
205        Type temp( targetResultType );
206        ResolveFormalGenericTypeParameter( temp, leftType, &userProc );
207
208        if( !returnType.Equals( temp ) ){
[75]209            return false;
[52]210        }
211    }
212
[75]213    return true;
[52]214}
215
[424]216const UserProc *ParamImpl::_OverloadSolution( const char *name, std::vector<const UserProc *> &subs, const Type &leftType, bool isEnabledReturnType ){
[353]217    const UserProc *pUserProc = NULL;
[52]218
[364]219    for( int level=OVERLOAD_MIN_LEVEL; level<=OVERLOAD_MAX_LEVEL; level++ )
220    {
221        BOOST_FOREACH( const UserProc *pTempUserProc, subs )
222        {
223            bool isErrored = false;
224            bool isHit = false;
[424]225            isHit = EvaluateOverloadScore( level, pTempUserProc->Params(), isEnabledReturnType?pTempUserProc->ReturnType():Type(), leftType, *pTempUserProc, isErrored );
[364]226            if( isErrored )
227            {
228                // 照合中にエラーが起きた場合
229                return NULL;
230            }
[140]231
[364]232            if( isHit )
233            {
[353]234                trace_for_overload( "レベル" << level << " ○適合..." << pTempUserProc->_paramStr );
[140]235
[353]236                if( pUserProc ){
[140]237                    if( isEnabledReturnType ){
[465]238                        compiler.errorMessenger.Output(52,name,cp);
[364]239                        return NULL;
[140]240                    }
241                    else{
242                        // 戻り値も比較するモードにして再びオーバーロード解決を試みる
[52]243
[167]244                        trace_for_overload( "戻り値も比較するモードに切り替えてオーバーロード解決を試みる" );
[52]245
[424]246                        return OverloadSolution( name, subs, leftType, true);
[140]247                    }
[52]248                }
[64]249
[75]250                pUserProc = pTempUserProc;
[52]251            }
[140]252            else
253            {
[353]254                trace_for_overload( "レベル" << level << " ×不適合..." << pTempUserProc->_paramStr );
[140]255            }
[52]256        }
257
[353]258        if( pUserProc ) break;
[52]259    }
260
[353]261    if( !pUserProc ){
[364]262        BOOST_FOREACH( const UserProc *pTempUserProc, subs )
263        {
[52]264            //エラーチェック
[364]265            if(pTempUserProc->Params().size()==this->ParmsNum)
266            {
267                if( pUserProc )
268                {
[465]269                    compiler.errorMessenger.Output(52,name,cp);
[364]270                    return NULL;
[52]271                }
272
[75]273                pUserProc=pTempUserProc;
[52]274            }
275        }
276    }
277
[353]278    if( !pUserProc )
279    {
[465]280        compiler.errorMessenger.OutputFatalError();
[52]281    }
282
[75]283    return pUserProc;
[52]284}
[424]285const UserProc *ParamImpl::OverloadSolution( const char *name, std::vector<const UserProc *> &subs, const Type &leftType, bool isEnabledReturnType ){
[167]286    trace_for_overload( "" );
287    trace_for_overload( "■■■■■■■■■■■■■■■■■■" );
288    trace_for_overload( "■■■ オーバーロード解決(" << name << ")" );
[52]289
[424]290    const UserProc *result = _OverloadSolution( name, subs, leftType, isEnabledReturnType );
[140]291
[167]292    trace_for_overload( "■■■ ここまで" );
293    trace_for_overload( "■■■■■■■■■■■■■■■■■■" );
294    trace_for_overload( "" );
[140]295
296    return result;
297}
298
[77]299void ParamImpl::ApplyDefaultParameters( const Parameters &params ){
300    if( ParmsNum == (int)params.size() ){
301        // デフォルト引数の適用が不必要なとき
302        return;
303    }
304
305    while( ParmsNum < (int)params.size() ){
306        Parameter &param = *params[ParmsNum];
307
308        Parms[ParmsNum]=(char *)HeapAlloc(hHeap,0,param.GetInitValue().size() + 1 );
309        lstrcpy(Parms[ParmsNum],param.GetInitValue().c_str() );
310        ParmsNum++;
311    }
312}
313
[523]314bool ParamImpl::ErrorCheck( const std::string &procName, const Parameters &params, int SecondParmNum ){
[75]315    if( SecondParmNum == -1 ) SecondParmNum = (int)params.size();
[52]316
[284]317    if(ParmsNum>(int)params.size()){
318        if( params.size() == 0 || params[params.size()-1]->GetBasicType()!=DEF_ELLIPSE ){
[73]319            //パラメータが多すぎるとき
[465]320            compiler.errorMessenger.Output(10,procName,cp);
[73]321            return false;
322        }
323    }
324    else if(ParmsNum<(int)params.size()){
325        if(ParmsNum<SecondParmNum){
326            if(params[ParmsNum]->GetBasicType()==DEF_ELLIPSE){
327                return true;
328            }
[52]329
[73]330            //パラメータが少なすぎるとき
[465]331            compiler.errorMessenger.Output(10,procName,cp);
[73]332            return false;
333        }
334
335        //省略パラメータに "0" を指定する
336        for(;ParmsNum < (int)params.size();ParmsNum++){
337            extern HANDLE hHeap;
338            char temporary[64];
339            if(params[ParmsNum]->IsRef() == false) lstrcpy(temporary,"0");
340            else sprintf(temporary,"%c%c0",1,ESC_BYVAL);
341            Parms[ParmsNum]=(char *)HeapAlloc(hHeap,0,lstrlen(temporary)+1);
342            lstrcpy(Parms[ParmsNum],temporary);
343        }
344    }
345
346    return true;
347}
348
349void ParamImpl::MacroParameterSupport( const Parameters &params ){
350    for(int i=0;i<ParmsNum;i++){
351        if(Parms[i][0]=='\0'){
352            extern HANDLE hHeap;
353            char temporary[64];
354            if( params[i]->IsRef() == false ) lstrcpy(temporary,"0");
355            else sprintf(temporary,"%c%c0",1,ESC_BYVAL);
356            HeapDefaultFree(Parms[i]);
357            Parms[i]=(char *)HeapAlloc(hHeap,0,lstrlen(temporary)+1);
358            lstrcpy(Parms[i],temporary);
359        }
360    }
361}
Note: See TracBrowser for help on using the repository browser.