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

Last change on this file since 660 was 527, checked in by dai_9181, 17 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.