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

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

ヘッダファイルを整理中

File size: 8.9 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        if( !returnType.Equals( targetResultType ) ){
205            return false;
206        }
207    }
208
209    return true;
210}
211
212const UserProc *ParamImpl::_OverloadSolution( const char *name, std::vector<const UserProc *> &subs, const Type &leftType, bool isEnabledReturnType ){
213    const UserProc *pUserProc = NULL;
214
215    for( int level=OVERLOAD_MIN_LEVEL; level<=OVERLOAD_MAX_LEVEL; level++ )
216    {
217        BOOST_FOREACH( const UserProc *pTempUserProc, subs )
218        {
219            bool isErrored = false;
220            bool isHit = false;
221            isHit = EvaluateOverloadScore( level, pTempUserProc->Params(), isEnabledReturnType?pTempUserProc->ReturnType():Type(), leftType, *pTempUserProc, isErrored );
222            if( isErrored )
223            {
224                // 照合中にエラーが起きた場合
225                return NULL;
226            }
227
228            if( isHit )
229            {
230                trace_for_overload( "レベル" << level << " ○適合..." << pTempUserProc->_paramStr );
231
232                if( pUserProc ){
233                    if( isEnabledReturnType ){
234                        compiler.errorMessenger.Output(52,name,cp);
235                        return NULL;
236                    }
237                    else{
238                        // 戻り値も比較するモードにして再びオーバーロード解決を試みる
239
240                        trace_for_overload( "戻り値も比較するモードに切り替えてオーバーロード解決を試みる" );
241
242                        return OverloadSolution( name, subs, leftType, true);
243                    }
244                }
245
246                pUserProc = pTempUserProc;
247            }
248            else
249            {
250                trace_for_overload( "レベル" << level << " ×不適合..." << pTempUserProc->_paramStr );
251            }
252        }
253
254        if( pUserProc ) break;
255    }
256
257    if( !pUserProc ){
258        BOOST_FOREACH( const UserProc *pTempUserProc, subs )
259        {
260            //エラーチェック
261            if(pTempUserProc->Params().size()==this->ParmsNum)
262            {
263                if( pUserProc )
264                {
265                    compiler.errorMessenger.Output(52,name,cp);
266                    return NULL;
267                }
268
269                pUserProc=pTempUserProc;
270            }
271        }
272    }
273
274    if( !pUserProc )
275    {
276        compiler.errorMessenger.OutputFatalError();
277    }
278
279    return pUserProc;
280}
281const UserProc *ParamImpl::OverloadSolution( const char *name, std::vector<const UserProc *> &subs, const Type &leftType, bool isEnabledReturnType ){
282    trace_for_overload( "" );
283    trace_for_overload( "■■■■■■■■■■■■■■■■■■" );
284    trace_for_overload( "■■■ オーバーロード解決(" << name << ")" );
285
286    const UserProc *result = _OverloadSolution( name, subs, leftType, isEnabledReturnType );
287
288    trace_for_overload( "■■■ ここまで" );
289    trace_for_overload( "■■■■■■■■■■■■■■■■■■" );
290    trace_for_overload( "" );
291
292    return result;
293}
294
295void ParamImpl::ApplyDefaultParameters( const Parameters &params ){
296    if( ParmsNum == (int)params.size() ){
297        // デフォルト引数の適用が不必要なとき
298        return;
299    }
300
301    while( ParmsNum < (int)params.size() ){
302        Parameter &param = *params[ParmsNum];
303
304        Parms[ParmsNum]=(char *)HeapAlloc(hHeap,0,param.GetInitValue().size() + 1 );
305        lstrcpy(Parms[ParmsNum],param.GetInitValue().c_str() );
306        ParmsNum++;
307    }
308}
309
310bool ParamImpl::ErrorCheck( const std::string &procName, const Parameters &params, int SecondParmNum ){
311    if( SecondParmNum == -1 ) SecondParmNum = (int)params.size();
312
313    if(ParmsNum>(int)params.size()){
314        if( params.size() == 0 || params[params.size()-1]->GetBasicType()!=DEF_ELLIPSE ){
315            //パラメータが多すぎるとき
316            compiler.errorMessenger.Output(10,procName,cp);
317            return false;
318        }
319    }
320    else if(ParmsNum<(int)params.size()){
321        if(ParmsNum<SecondParmNum){
322            if(params[ParmsNum]->GetBasicType()==DEF_ELLIPSE){
323                return true;
324            }
325
326            //パラメータが少なすぎるとき
327            compiler.errorMessenger.Output(10,procName,cp);
328            return false;
329        }
330
331        //省略パラメータに "0" を指定する
332        for(;ParmsNum < (int)params.size();ParmsNum++){
333            extern HANDLE hHeap;
334            char temporary[64];
335            if(params[ParmsNum]->IsRef() == false) lstrcpy(temporary,"0");
336            else sprintf(temporary,"%c%c0",1,ESC_BYVAL);
337            Parms[ParmsNum]=(char *)HeapAlloc(hHeap,0,lstrlen(temporary)+1);
338            lstrcpy(Parms[ParmsNum],temporary);
339        }
340    }
341
342    return true;
343}
344
345void ParamImpl::MacroParameterSupport( const Parameters &params ){
346    for(int i=0;i<ParmsNum;i++){
347        if(Parms[i][0]=='\0'){
348            extern HANDLE hHeap;
349            char temporary[64];
350            if( params[i]->IsRef() == false ) lstrcpy(temporary,"0");
351            else sprintf(temporary,"%c%c0",1,ESC_BYVAL);
352            HeapDefaultFree(Parms[i]);
353            Parms[i]=(char *)HeapAlloc(hHeap,0,lstrlen(temporary)+1);
354            lstrcpy(Parms[i],temporary);
355        }
356    }
357}
Note: See TracBrowser for help on using the repository browser.