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

Last change on this file since 742 was 708, checked in by dai_9181, 16 years ago
  • #184への対応。ByRef引数を持つデリゲートを宣言するとコンパイルできないバグを修正。
  • オーバーロード用のパラメータ比較にByRef/ByValの相違を考慮するようにした。
File size: 9.1 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 types.push_back( Type() );
313 }
314}
315
316bool ParamImpl::ErrorCheck( const std::string &procName, const Parameters &params, int SecondParmNum ){
317 if( SecondParmNum == -1 ) SecondParmNum = (int)params.size();
318
319 if(ParmsNum>(int)params.size()){
320 if( params.size() == 0 || params[params.size()-1]->GetBasicType()!=DEF_ELLIPSE ){
321 //パラメータが多すぎるとき
322 compiler.errorMessenger.Output(10,procName,cp);
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 }
331
332 //パラメータが少なすぎるとき
333 compiler.errorMessenger.Output(10,procName,cp);
334 return false;
335 }
336
337 //省略パラメータに "0" を指定する
338 while( ParmsNum < (int)params.size() )
339 {
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);
346
347 ParmsNum++;
348
349 types.push_back( Type() );
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.