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

Last change on this file since 479 was 465, checked in by dai_9181, 17 years ago

Messenger/ErrorMessengerクラスを導入。SetError関数によるエラー生成を廃止した。

File size: 9.0 KB
RevLine 
[206]1#include "stdafx.h"
2
[167]3#include <Program.h>
[165]4
[52]5#include "common.h"
6
7#ifdef _AMD64_
8#include "../BasicCompiler64/opcode.h"
9#else
10#include "../BasicCompiler32/opcode.h"
11#endif
12
[78]13#define OVERLOAD_MIN_LEVEL 0
[111]14#define OVERLOAD_MAX_LEVEL 6
[78]15#define OVERLOAD_LEVEL0 0 // 型調整なし。厳密に等しい
[90]16#define OVERLOAD_LEVEL1 1 // 型調整なし。レベル1以上はオブジェクトの場合は派生関係を考慮
[111]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 // 型調整あり。数値型/クラス型レベルでの同一性チェック
[78]22
[75]23ParamImpl::ParamImpl(const char *buffer):
24 returnType()
25{
[52]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];
[319]44 if( buffer[i] == '\0' )
45 {
[465]46 compiler.errorMessenger.OutputFatalError();
[319]47 break;
48 }
[52]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
[75]78 types.push_back( Type() );
79
[52]80 if(buffer[i]==',') i++;
81 }
82}
[75]83ParamImpl::ParamImpl(const Parameters &params):
84 returnType()
85{
86 ParmsNum = 0;
[182]87 BOOST_FOREACH( Parameter *pParam, params ){
[75]88 Parms[ParmsNum]=0;
89 ParmsNum++;
[52]90
[75]91 types.push_back( *pParam );
[73]92 }
93}
[71]94ParamImpl::~ParamImpl(){
[52]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
[75]105void ParamImpl::SetReturnType( const Type &returnType ){
106 this->returnType = returnType;
[52]107}
108
[424]109bool ParamImpl::EvaluateOverloadScore( int level, const Parameters &targetParms, const Type &targetResultType, const Type &leftType, const UserProc &userProc, bool &isErrored ){
[52]110 //パラメータを識別してオーバーロードを解決
111
[364]112 isErrored = false;
113
[52]114 //パラメータの個数が不一致の場合
[75]115 int max = (int)targetParms.size();
[77]116
117 if( ParmsNum > max ){
118 // 実引数が駆り引数より多いとき
119 // ※無条件で不一致
[75]120 return false;
121 }
[52]122
[73]123 Type argType;
124 for(int i=0;i<max;i++){
[75]125 Parameter &param = *targetParms[i];
[73]126
[424]127 Type paramType( param );
128 ResolveFormalGenericTypeParameter( paramType, leftType, &userProc );
129
[77]130 if( i >= ParmsNum ){
131 // 引数が多いとき
132 if( param.GetInitValue().size() > 0 ){
133 // 初期値が指定されているパラメータを考慮
134 return true;
135 }
136 else{
137 return false;
138 }
139 }
140
[52]141 if(Parms[i]){
[73]142 Type nullParam( DEF_NON );
143
[364]144 if( !NumOpe_GetType(Parms[i],
[424]145 ( level <= OVERLOAD_LEVEL3 )? nullParam : paramType,
[364]146 argType) )
147 {
148 isErrored = true;
149 return false;
150 }
[52]151 }
152 else{
[75]153 argType = types[i];
[52]154 }
155
[424]156 if( ( argType.IsObject() && paramType.IsObject() ) || argType.GetBasicType() == paramType.GetBasicType() )
157 {
158 if( argType.IsStruct() ){
159 if(argType.GetIndex()!=paramType.GetIndex()){
160 return false;
161 }
162 }
163 else if( argType.IsObject() ){
164 if( level == OVERLOAD_LEVEL0 ){
165 if( !paramType.GetClass().IsEquals( &argType.GetClass() ) ){
166 return false;
167 }
168 }
169 else{
170 if( !paramType.GetClass().IsEqualsOrSubClass( &argType.GetClass() ) ){
171 return false;
172 }
173 }
174 }
175 }
176 else
177 {
[111]178 if( level == OVERLOAD_LEVEL0 || level == OVERLOAD_LEVEL1 || level==OVERLOAD_LEVEL4 ){
[75]179 return false;
[52]180 }
[111]181 else if( level == OVERLOAD_LEVEL2 ){
[424]182 if( !(argType.IsWhole() && paramType.IsWhole() && argType.GetBasicSize() == paramType.GetBasicSize() ) ){
[111]183 // サイズ違い
184 return false;
185 }
186 }
187 else if( level == OVERLOAD_LEVEL3 || level==OVERLOAD_LEVEL5){
[52]188 if(!(
[424]189 argType.IsWhole()&&paramType.IsWhole()||
190 argType.IsReal()&&paramType.IsReal()
[75]191 )){
192 return false;
193 }
[424]194 if( argType.IsPointer() || paramType.IsPointer() )
[140]195 {
196 // ポインタ型の不整合は認めない
197 return false;
198 }
[52]199 }
[111]200 else if(level==OVERLOAD_LEVEL6){
[424]201 if(argType.IsObject()||paramType.IsObject()) return false;
[52]202 }
203 }
204 }
205
[75]206 if( !targetResultType.IsNull() ){
[52]207 //戻り値も比較対象にする
[75]208 if( !returnType.Equals( targetResultType ) ){
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++;
311 }
312}
313
[75]314bool ParamImpl::ErrorCheck( const string &procName, const Parameters &params, int SecondParmNum ){
315 if( SecondParmNum == -1 ) SecondParmNum = (int)params.size();
[52]316
[284]317 if(ParmsNum>(int)params.size()){
318 if( params.size() == 0 || params[params.size()-1]->GetBasicType()!=DEF_ELLIPSE ){
[73]319 //パラメータが多すぎるとき
[465]320 compiler.errorMessenger.Output(10,procName,cp);
[73]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 }
[52]329
[73]330 //パラメータが少なすぎるとき
[465]331 compiler.errorMessenger.Output(10,procName,cp);
[73]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.