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
Line 
1#include "stdafx.h"
2
3#ifdef _AMD64_
4#include "../compiler_x64/opcode.h"
5#else
6#include "../compiler_x86/opcode.h"
7#endif
8
9#define OVERLOAD_MIN_LEVEL 0
10#define OVERLOAD_MAX_LEVEL 6
11#define OVERLOAD_LEVEL0 0       // 型調整なし。厳密に等しい
12#define OVERLOAD_LEVEL1 1       // 型調整なし。レベル1以上はオブジェクトの場合は派生関係を考慮
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       // 型調整あり。数値型/クラス型レベルでの同一性チェック
18
19ParamImpl::ParamImpl(const char *buffer):
20    returnType()
21{
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];
40                    if( buffer[i] == '\0' )
41                    {
42                        compiler.errorMessenger.OutputFatalError();
43                        break;
44                    }
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
74        types.push_back( Type() );
75
76        if(buffer[i]==',') i++;
77    }
78}
79ParamImpl::ParamImpl(const Parameters &params):
80    returnType()
81{
82    ParmsNum = 0;
83    BOOST_FOREACH( Parameter *pParam, params ){
84        Parms[ParmsNum]=0;
85        ParmsNum++;
86
87        types.push_back( *pParam );
88    }
89}
90ParamImpl::~ParamImpl(){
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
101void ParamImpl::SetReturnType( const Type &returnType ){
102    this->returnType = returnType;
103}
104
105bool ParamImpl::EvaluateOverloadScore( int level, const Parameters &targetParms, const Type &targetResultType, const Type &leftType, const UserProc &userProc, bool &isErrored ){
106    //パラメータを識別してオーバーロードを解決
107
108    isErrored = false;
109
110    //パラメータの個数が不一致の場合
111    int max = (int)targetParms.size();
112
113    if( ParmsNum > max ){
114        // 実引数が駆り引数より多いとき
115        // ※無条件で不一致
116        return false;
117    }
118
119    Type argType;
120    for(int i=0;i<max;i++){
121        Parameter &param = *targetParms[i];
122
123        Type paramType( param );
124        ResolveFormalGenericTypeParameter( paramType, leftType, &userProc );
125
126        if( i >= ParmsNum ){
127            // 引数が多いとき
128            if( param.GetInitValue().size() > 0 ){
129                // 初期値が指定されているパラメータを考慮
130                return true;
131            }
132            else{
133                return false;
134            }
135        }
136
137        if(Parms[i]){
138            Type nullParam( DEF_NON );
139
140            if( !NumOpe_GetType(Parms[i],
141                ( level <= OVERLOAD_LEVEL3 )? nullParam : paramType,
142                argType) )
143            {
144                isErrored = true;
145                return false;
146            }
147        }
148        else{
149            argType = types[i];
150        }
151
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        {
174            if( level == OVERLOAD_LEVEL0 || level == OVERLOAD_LEVEL1 || level==OVERLOAD_LEVEL4 ){
175                return false;
176            }
177            else if( level == OVERLOAD_LEVEL2 ){
178                if( !(argType.IsWhole() && paramType.IsWhole() && argType.GetBasicSize() == paramType.GetBasicSize() ) ){
179                    // サイズ違い
180                    return false;
181                }
182            }
183            else if( level == OVERLOAD_LEVEL3 || level==OVERLOAD_LEVEL5){
184                if(!(
185                    argType.IsWhole()&&paramType.IsWhole()||
186                    argType.IsReal()&&paramType.IsReal()
187                    )){
188                        return false;
189                }
190                if( argType.IsPointer() || paramType.IsPointer() )
191                {
192                    // ポインタ型の不整合は認めない
193                    return false;
194                }
195            }
196            else if(level==OVERLOAD_LEVEL6){
197                if(argType.IsObject()||paramType.IsObject()) return false;
198            }
199        }
200    }
201
202    if( !targetResultType.IsNull() ){
203        //戻り値も比較対象にする
204
205        Type temp( targetResultType );
206        ResolveFormalGenericTypeParameter( temp, leftType, &userProc );
207
208        if( !returnType.Equals( temp ) ){
209            return false;
210        }
211    }
212
213    return true;
214}
215
216const UserProc *ParamImpl::_OverloadSolution( const char *name, std::vector<const UserProc *> &subs, const Type &leftType, bool isEnabledReturnType ){
217    const UserProc *pUserProc = NULL;
218
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;
225            isHit = EvaluateOverloadScore( level, pTempUserProc->Params(), isEnabledReturnType?pTempUserProc->ReturnType():Type(), leftType, *pTempUserProc, isErrored );
226            if( isErrored )
227            {
228                // 照合中にエラーが起きた場合
229                return NULL;
230            }
231
232            if( isHit )
233            {
234                trace_for_overload( "レベル" << level << " ○適合..." << pTempUserProc->_paramStr );
235
236                if( pUserProc ){
237                    if( isEnabledReturnType ){
238                        compiler.errorMessenger.Output(52,name,cp);
239                        return NULL;
240                    }
241                    else{
242                        // 戻り値も比較するモードにして再びオーバーロード解決を試みる
243
244                        trace_for_overload( "戻り値も比較するモードに切り替えてオーバーロード解決を試みる" );
245
246                        return OverloadSolution( name, subs, leftType, true);
247                    }
248                }
249
250                pUserProc = pTempUserProc;
251            }
252            else
253            {
254                trace_for_overload( "レベル" << level << " ×不適合..." << pTempUserProc->_paramStr );
255            }
256        }
257
258        if( pUserProc ) break;
259    }
260
261    if( !pUserProc ){
262        BOOST_FOREACH( const UserProc *pTempUserProc, subs )
263        {
264            //エラーチェック
265            if(pTempUserProc->Params().size()==this->ParmsNum)
266            {
267                if( pUserProc )
268                {
269                    compiler.errorMessenger.Output(52,name,cp);
270                    return NULL;
271                }
272
273                pUserProc=pTempUserProc;
274            }
275        }
276    }
277
278    if( !pUserProc )
279    {
280        compiler.errorMessenger.OutputFatalError();
281    }
282
283    return pUserProc;
284}
285const UserProc *ParamImpl::OverloadSolution( const char *name, std::vector<const UserProc *> &subs, const Type &leftType, bool isEnabledReturnType ){
286    trace_for_overload( "" );
287    trace_for_overload( "■■■■■■■■■■■■■■■■■■" );
288    trace_for_overload( "■■■ オーバーロード解決(" << name << ")" );
289
290    const UserProc *result = _OverloadSolution( name, subs, leftType, isEnabledReturnType );
291
292    trace_for_overload( "■■■ ここまで" );
293    trace_for_overload( "■■■■■■■■■■■■■■■■■■" );
294    trace_for_overload( "" );
295
296    return result;
297}
298
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
314bool ParamImpl::ErrorCheck( const std::string &procName, const Parameters &params, int SecondParmNum ){
315    if( SecondParmNum == -1 ) SecondParmNum = (int)params.size();
316
317    if(ParmsNum>(int)params.size()){
318        if( params.size() == 0 || params[params.size()-1]->GetBasicType()!=DEF_ELLIPSE ){
319            //パラメータが多すぎるとき
320            compiler.errorMessenger.Output(10,procName,cp);
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            }
329
330            //パラメータが少なすぎるとき
331            compiler.errorMessenger.Output(10,procName,cp);
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.