source: dev/trunk/abdev/BasicCompiler_Common/ParamImpl.cpp @ 319

Last change on this file since 319 was 319, checked in by dai_9181, 16 years ago

GCのバグをいくつか修正

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