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

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

インターフェイス実装周りの仕様整備

File size: 8.2 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 {
46 SetError();
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
[140]109bool ParamImpl::EvaluateOverloadScore( int level, const Parameters &targetParms, const Type &targetResultType ){
[52]110 //パラメータを識別してオーバーロードを解決
111
112 //パラメータの個数が不一致の場合
[75]113 int max = (int)targetParms.size();
[77]114
115 if( ParmsNum > max ){
116 // 実引数が駆り引数より多いとき
117 // ※無条件で不一致
[75]118 return false;
119 }
[52]120
[73]121 Type argType;
122 for(int i=0;i<max;i++){
[75]123 Parameter &param = *targetParms[i];
[73]124
[77]125 if( i >= ParmsNum ){
126 // 引数が多いとき
127 if( param.GetInitValue().size() > 0 ){
128 // 初期値が指定されているパラメータを考慮
129 return true;
130 }
131 else{
132 return false;
133 }
134 }
135
[52]136 if(Parms[i]){
[73]137 Type nullParam( DEF_NON );
138
139 NumOpe_GetType(Parms[i],
[111]140 ( level <= OVERLOAD_LEVEL3 )? nullParam : param,
[73]141 argType);
[52]142 }
143 else{
[75]144 argType = types[i];
[52]145 }
146
[73]147 if(argType.GetBasicType()!=param.GetBasicType()){
[111]148 if( level == OVERLOAD_LEVEL0 || level == OVERLOAD_LEVEL1 || level==OVERLOAD_LEVEL4 ){
[75]149 return false;
[52]150 }
[111]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){
[52]158 if(!(
[78]159 argType.IsWhole()&&param.IsWhole()||
160 argType.IsReal()&&param.IsReal()
[75]161 )){
162 return false;
163 }
[140]164 if( argType.IsPointer() || param.IsPointer() )
165 {
166 // ポインタ型の不整合は認めない
167 return false;
168 }
[52]169 }
[111]170 else if(level==OVERLOAD_LEVEL6){
[78]171 if(argType.IsObject()||param.IsObject()) return false;
[52]172 }
173 }
174 else{
[84]175 if( NATURAL_TYPE(argType.GetBasicType())==DEF_STRUCT){
[75]176 if(argType.GetIndex()!=param.GetIndex()){
177 return false;
178 }
[52]179 }
[84]180 else if( NATURAL_TYPE(argType.GetBasicType())==DEF_OBJECT ){
[90]181 if( level == OVERLOAD_LEVEL0 ){
182 if( !param.GetClass().IsEquals( &argType.GetClass() ) ){
183 return false;
184 }
[84]185 }
[90]186 else{
187 if( !param.GetClass().IsEqualsOrSubClass( &argType.GetClass() ) ){
188 return false;
189 }
190 }
[84]191 }
[52]192 }
193 }
194
[75]195 if( !targetResultType.IsNull() ){
[52]196 //戻り値も比較対象にする
[75]197 if( !returnType.Equals( targetResultType ) ){
198 return false;
[52]199 }
200 }
201
[75]202 return true;
[52]203}
204
[206]205const UserProc *ParamImpl::_OverloadSolution( const char *name, std::vector<const UserProc *> &subs, bool isEnabledReturnType ){
[353]206 const UserProc *pUserProc = NULL;
[52]207
[64]208 for( int level=OVERLOAD_MIN_LEVEL; level<=OVERLOAD_MAX_LEVEL; level++ ){
[140]209
[206]210 BOOST_FOREACH( const UserProc *pTempUserProc, subs ){
[52]211
[140]212 if(EvaluateOverloadScore( level, pTempUserProc->Params(), isEnabledReturnType?pTempUserProc->ReturnType():Type() )){
[353]213 trace_for_overload( "レベル" << level << " ○適合..." << pTempUserProc->_paramStr );
[140]214
[353]215 if( pUserProc ){
[140]216 if( isEnabledReturnType ){
217 SetError(52,name,cp);
218 }
219 else{
220 // 戻り値も比較するモードにして再びオーバーロード解決を試みる
[52]221
[167]222 trace_for_overload( "戻り値も比較するモードに切り替えてオーバーロード解決を試みる" );
[52]223
[140]224 return OverloadSolution(name,subs, true);
225 }
[52]226 }
[64]227
[75]228 pUserProc = pTempUserProc;
[52]229 }
[140]230 else
231 {
[353]232 trace_for_overload( "レベル" << level << " ×不適合..." << pTempUserProc->_paramStr );
[140]233 }
[52]234 }
235
[353]236 if( pUserProc ) break;
[52]237 }
238
[353]239 if( !pUserProc ){
[206]240 BOOST_FOREACH( const UserProc *pTempUserProc, subs ){
[52]241
242 //エラーチェック
[75]243 if(pTempUserProc->Params().size()==this->ParmsNum){
[353]244 if( pUserProc ){
245 SetError(52,name,cp);
[52]246 }
247
[75]248 pUserProc=pTempUserProc;
[52]249 }
250 }
251 }
252
[353]253 if( !pUserProc )
254 {
255 SetError();
[52]256 }
257
[75]258 return pUserProc;
[52]259}
[206]260const UserProc *ParamImpl::OverloadSolution( const char *name, std::vector<const UserProc *> &subs, bool isEnabledReturnType ){
[167]261 trace_for_overload( "" );
262 trace_for_overload( "■■■■■■■■■■■■■■■■■■" );
263 trace_for_overload( "■■■ オーバーロード解決(" << name << ")" );
[52]264
[206]265 const UserProc *result = _OverloadSolution( name, subs, isEnabledReturnType );
[140]266
[167]267 trace_for_overload( "■■■ ここまで" );
268 trace_for_overload( "■■■■■■■■■■■■■■■■■■" );
269 trace_for_overload( "" );
[140]270
271 return result;
272}
273
[77]274void ParamImpl::ApplyDefaultParameters( const Parameters &params ){
275 if( ParmsNum == (int)params.size() ){
276 // デフォルト引数の適用が不必要なとき
277 return;
278 }
279
280 while( ParmsNum < (int)params.size() ){
281 Parameter &param = *params[ParmsNum];
282
283 Parms[ParmsNum]=(char *)HeapAlloc(hHeap,0,param.GetInitValue().size() + 1 );
284 lstrcpy(Parms[ParmsNum],param.GetInitValue().c_str() );
285 ParmsNum++;
286 }
287}
288
[75]289bool ParamImpl::ErrorCheck( const string &procName, const Parameters &params, int SecondParmNum ){
290 if( SecondParmNum == -1 ) SecondParmNum = (int)params.size();
[52]291
[284]292 if(ParmsNum>(int)params.size()){
293 if( params.size() == 0 || params[params.size()-1]->GetBasicType()!=DEF_ELLIPSE ){
[73]294 //パラメータが多すぎるとき
295 SetError(10,procName,cp);
296 return false;
297 }
298 }
299 else if(ParmsNum<(int)params.size()){
300 if(ParmsNum<SecondParmNum){
301 if(params[ParmsNum]->GetBasicType()==DEF_ELLIPSE){
302 return true;
303 }
[52]304
[73]305 //パラメータが少なすぎるとき
306 SetError(10,procName,cp);
307 return false;
308 }
309
310 //省略パラメータに "0" を指定する
311 for(;ParmsNum < (int)params.size();ParmsNum++){
312 extern HANDLE hHeap;
313 char temporary[64];
314 if(params[ParmsNum]->IsRef() == false) lstrcpy(temporary,"0");
315 else sprintf(temporary,"%c%c0",1,ESC_BYVAL);
316 Parms[ParmsNum]=(char *)HeapAlloc(hHeap,0,lstrlen(temporary)+1);
317 lstrcpy(Parms[ParmsNum],temporary);
318 }
319 }
320
321 return true;
322}
323
324void ParamImpl::MacroParameterSupport( const Parameters &params ){
325 for(int i=0;i<ParmsNum;i++){
326 if(Parms[i][0]=='\0'){
327 extern HANDLE hHeap;
328 char temporary[64];
329 if( params[i]->IsRef() == false ) lstrcpy(temporary,"0");
330 else sprintf(temporary,"%c%c0",1,ESC_BYVAL);
331 HeapDefaultFree(Parms[i]);
332 Parms[i]=(char *)HeapAlloc(hHeap,0,lstrlen(temporary)+1);
333 lstrcpy(Parms[i],temporary);
334 }
335 }
336}
Note: See TracBrowser for help on using the repository browser.