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

Last change on this file since 724 was 708, checked in by dai_9181, 16 years ago
  • #184への対応。ByRef引数を持つデリゲートを宣言するとコンパイルできないバグを修正。
  • オーバーロード用のパラメータ比較にByRef/ByValの相違を考慮するようにした。
File size: 9.1 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++;
[708]311
312 types.push_back( Type() );
[77]313 }
314}
315
[523]316bool ParamImpl::ErrorCheck( const std::string &procName, const Parameters &params, int SecondParmNum ){
[75]317 if( SecondParmNum == -1 ) SecondParmNum = (int)params.size();
[52]318
[284]319 if(ParmsNum>(int)params.size()){
320 if( params.size() == 0 || params[params.size()-1]->GetBasicType()!=DEF_ELLIPSE ){
[73]321 //パラメータが多すぎるとき
[465]322 compiler.errorMessenger.Output(10,procName,cp);
[73]323 return false;
324 }
325 }
326 else if(ParmsNum<(int)params.size()){
327 if(ParmsNum<SecondParmNum){
328 if(params[ParmsNum]->GetBasicType()==DEF_ELLIPSE){
329 return true;
330 }
[52]331
[73]332 //パラメータが少なすぎるとき
[465]333 compiler.errorMessenger.Output(10,procName,cp);
[73]334 return false;
335 }
336
337 //省略パラメータに "0" を指定する
[708]338 while( ParmsNum < (int)params.size() )
339 {
[73]340 extern HANDLE hHeap;
341 char temporary[64];
342 if(params[ParmsNum]->IsRef() == false) lstrcpy(temporary,"0");
343 else sprintf(temporary,"%c%c0",1,ESC_BYVAL);
344 Parms[ParmsNum]=(char *)HeapAlloc(hHeap,0,lstrlen(temporary)+1);
345 lstrcpy(Parms[ParmsNum],temporary);
[708]346
347 ParmsNum++;
348
349 types.push_back( Type() );
[73]350 }
351 }
352
353 return true;
354}
355
356void ParamImpl::MacroParameterSupport( const Parameters &params ){
357 for(int i=0;i<ParmsNum;i++){
358 if(Parms[i][0]=='\0'){
359 extern HANDLE hHeap;
360 char temporary[64];
361 if( params[i]->IsRef() == false ) lstrcpy(temporary,"0");
362 else sprintf(temporary,"%c%c0",1,ESC_BYVAL);
363 HeapDefaultFree(Parms[i]);
364 Parms[i]=(char *)HeapAlloc(hHeap,0,lstrlen(temporary)+1);
365 lstrcpy(Parms[i],temporary);
366 }
367 }
368}
Note: See TracBrowser for help on using the repository browser.