source: dev/trunk/ab5.0/abdev/BasicCompiler_Common/src/Procedure.cpp@ 571

Last change on this file since 571 was 571, checked in by dai_9181, 16 years ago

・LexicalAnalyzer::AnalyzeParameterの第二パラメータをstringからStringsに変更した。
・UserProc::SetParamsAndReturnTypeメソッド内で行っているパラメータ解析処理をLexicalAnalyzer::AnalyzeParameterメソッドを使用したコードに書き直した。

File size: 17.6 KB
Line 
1#include "stdafx.h"
2
3#include <Compiler.h>
4#include <Procedure.h>
5
6#include "../common.h"
7#ifdef _AMD64_
8#include "../../compiler_x64/opcode.h"
9#else
10#include "../../compiler_x86/opcode.h"
11#endif
12
13using namespace ActiveBasic::Compiler;
14
15
16bool UserProc::IsEqualForOverride( const Types &actualTypeParametersForThisProc, const UserProc *pUserProc ) const
17{
18 if( this->GetName() == pUserProc->GetName() // 名前空間及び名前が等しい
19 && this->Params().Equals( actualTypeParametersForThisProc, pUserProc->Params() ) ) // パラメータが等しい
20 {
21 if( this->returnType.Equals( pUserProc->returnType ) )
22 {
23 // 戻り値が等しい
24 return true;
25 }
26 else if( this->returnType.IsCovariant( pUserProc->returnType ) )
27 {
28 // 戻り値が共変
29 return true;
30 }
31 else if( this->returnType.IsTypeParameter() )
32 {
33 // 型パラメータだったとき
34
35 if( actualTypeParametersForThisProc[this->returnType.GetFormalTypeIndex()].Equals( pUserProc->returnType ) )
36 {
37 // 戻り値が等しい
38 return true;
39 }
40 else if( actualTypeParametersForThisProc[this->returnType.GetFormalTypeIndex()].IsCovariant( pUserProc->returnType ) )
41 {
42 // 戻り値が共変
43 return true;
44 }
45 }
46 }
47 return false;
48}
49
50
51std::string UserProc::GetFullName() const
52{
53 if( HasParentClass() ){
54 return GetParentClass().GetName() + "." + GetName();
55 }
56
57 return GetName();
58}
59bool UserProc::IsCastOperator() const
60{
61 if( GetName()[0] == 1 && GetName()[1] == ESC_OPERATOR && GetName()[2] == CALC_AS )
62 {
63 return true;
64 }
65 return false;
66}
67const NamespaceScopes &UserProc::GetNamespaceScopes() const
68{
69 if( HasParentClass() ){
70 return GetParentClassPtr()->GetNamespaceScopes();
71 }
72 return Symbol::GetNamespaceScopes();
73}
74const NamespaceScopesCollection &UserProc::GetImportedNamespaces() const
75{
76 if( pParentClass )
77 {
78 return pParentClass->GetImportedNamespaces();
79 }
80 return importedNamespaces;
81}
82bool UserProc::IsVirtual() const
83{
84 if( pMethod == NULL ){
85 return false;
86 }
87 return ( pMethod->IsVirtual() != 0 );
88}
89const CMethod &UserProc::GetMethod() const
90{
91 if( !HasParentClass() )
92 {
93 Jenga::Throw( "グローバル関数に対してUserProc::GetMethodメソッドが呼ばれた" );
94 }
95 return *pMethod;
96}
97
98bool UserProc::SetParamsAndReturnType( const char *sourceOfParams, int nowLine, bool isStatic ){
99 int i = 0;
100
101 //ソースコードの位置
102 this->codePos = nowLine;
103
104 //パラメータ
105 if(sourceOfParams[i]!='('){
106 compiler.errorMessenger.Output(1,NULL,nowLine);
107 return false;
108 }
109 if(sourceOfParams[i + 1]!=')'&& this->pParentClass ){
110 //クラスのメンバ関数の場合のみ、デストラクタにパラメータがある場合にエラーをだす
111 if(this->GetName()[0]=='~'){
112 compiler.errorMessenger.Output(114,NULL,nowLine);
113 return false;
114 }
115 }
116
117 // カッコ内のパラメータ文字列を取得
118 char parametersStr1[8192];
119 char parametersStr2[8192] = "";
120 i += GetStringInPare( parametersStr1, sourceOfParams + i, true );
121 if( sourceOfParams[i] == '(' )
122 {
123 i += GetStringInPare( parametersStr2, sourceOfParams + i, true );
124 }
125
126 // 戻り値文字列を取得
127 char returnTypeStr[VN_SIZE] = "";
128 if( sourceOfParams[i] )
129 {
130 if( sourceOfParams[i] == 1 && sourceOfParams[i+1] == ESC_AS )
131 {
132 if( !this->IsFunction() ){
133 // Sub/Macroの場合
134 compiler.errorMessenger.Output(38,this->GetName(),nowLine);
135 }
136
137 lstrcpy( returnTypeStr, sourceOfParams + i + 2 );
138 }
139 else
140 {
141 compiler.errorMessenger.Output(1,NULL,nowLine);
142 return false;
143 }
144 }
145
146 Jenga::Common::Strings parameters;
147
148 // パラメータ
149 SplitParameter( parametersStr1, parameters );
150 ActiveBasic::Compiler::LexicalAnalyzer::AnalyzeParameter( params, parameters, nowLine );
151
152 // 省略可能パラメータ(古い仕様。非推奨)
153 this->secondParmNum = (int)this->params.size();
154 SplitParameter( parametersStr2, parameters );
155 ActiveBasic::Compiler::LexicalAnalyzer::AnalyzeParameter( params, parameters, nowLine );
156
157
158 if(returnTypeStr[0]){
159 ///////////////////
160 // 戻り値を取得
161 ///////////////////
162
163 if( !this->IsFunction() ){
164 // Sub/Macroの場合
165 compiler.errorMessenger.Output(38,this->GetName(),nowLine);
166 }
167
168 if( this->pParentClass ){
169 if( this->GetName() == this->pParentClass->GetName() ||
170 this->GetName()[0]=='~'){
171 //クラスのコンストラクタ、デストラクタがFunction定義の場合はエラーをだす
172 compiler.errorMessenger.Output(115,NULL,nowLine);
173 }
174 }
175
176 compiler.StringToType( returnTypeStr, this->returnType );
177 if( this->returnType.IsNull() )
178 {
179 compiler.errorMessenger.Output(3,returnTypeStr,nowLine);
180 }
181 }
182 else{
183 if( this->IsFunction() )
184 {
185 // Function定義なのに、戻り値の型がセットされていない
186 compiler.errorMessenger.Output(-104,this->GetName().c_str(),nowLine);
187
188 this->returnType.SetBasicType( DEF_DOUBLE );
189 }
190 else
191 {
192 //戻り値なしのSub定義
193 this->returnType.SetNull();
194 }
195 }
196
197 //リアルパラメータ領域を取得(_System_LocalThisを考慮して2つだけ多く確保する場合がある)
198
199 if( this->pParentClass && isStatic == false ){
200 //オブジェクトメンバの場合は、第一パラメータを_System_LocalThis引き渡し用として利用
201 std::string name = "_System_LocalThis";
202 Type type( DEF_PTR_VOID );
203 this->realParams.push_back( new Parameter( name, type ) );
204 }
205
206 if( this->returnType.IsStruct() ){
207 //構造体を戻り値として持つ場合
208 //※第一パラメータ(Thisポインタありの場合は第二パラメータ)を戻り値用の参照宣言にする
209
210 std::string name = this->GetName();
211 if(name[0]==1&&name[1]==ESC_OPERATOR){
212 name="_System_ReturnValue";
213 }
214 Type type( DEF_STRUCT, this->returnType.GetIndex() );
215 this->realParams.push_back( new Parameter( name, type, true ) );
216 }
217
218 //パラメータをコピー
219 BOOST_FOREACH( Parameter *pParam, params ){
220 this->realParams.push_back( new Parameter( *pParam ) );
221 }
222
223 return true;
224}
225
226const UserProc *UserProc::pGlobalProc = NULL;
227
228
229bool UserProcs::Insert( UserProc *pUserProc, int nowLine )
230{
231 /////////////////////////////////
232 // ハッシュデータに追加
233 /////////////////////////////////
234
235 if( !Put( pUserProc ) )
236 {
237 // 重複しているため、失敗
238 compiler.errorMessenger.Output(15,pUserProc->GetName().c_str(),nowLine);
239 return false;
240 }
241
242 return true;
243}
244
245void UserProcs::EnumGlobalProcs( const char *simpleName, const char *localName, std::vector<const UserProc *> &subs )
246{
247 ///////////////////////////
248 // グローバル関数を検索
249 ///////////////////////////
250
251 // ハッシュ値を取得
252 UserProc *pUserProc = GetHashArrayElement( simpleName );
253 while(pUserProc){
254 if( pUserProc->IsGlobalProcedure() ){
255 if( pUserProc->IsEqualSymbol( LexicalAnalyzer::FullNameToSymbol( localName ) ) ){
256 subs.push_back( pUserProc );
257 }
258 }
259
260 pUserProc=pUserProc->GetChainNext();
261 }
262}
263
264bool DllProc::SetParamsAndReturnType( const char *sourceOfParams, int nowLine ){
265 int i = 0;
266 int i2,i3,sw;
267 char temporary[8192],temp2[VN_SIZE];
268
269 //ソースコードの位置
270 this->codePos = nowLine;
271
272 //パラメータ
273 if(sourceOfParams[i]!='('){
274 compiler.errorMessenger.Output(1,NULL,nowLine);
275 return 0;
276 }
277 i++;
278
279 while(1){
280 if(sourceOfParams[i]==')') break;
281
282 //ByRef
283 bool isRef;
284 if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_BYVAL){
285 isRef = false;
286 i+=2;
287 }
288 else if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_BYREF){
289 isRef = true;
290 i+=2;
291 }
292 else isRef = false;
293
294 //パラメータ名
295 bool isArray = false;
296 Subscripts subscripts;
297 char name[VN_SIZE];
298 sw=0;
299 for(i2=0;;i++,i2++){
300 if(sourceOfParams[i]=='('){
301 if(!sw) sw=1;
302
303 i3=GetStringInPare(name+i2,sourceOfParams+i);
304 i2+=i3-1;
305 i+=i3-1;
306 continue;
307 }
308 if(sourceOfParams[i]=='['){
309 if(!sw) sw=1;
310
311 i3=GetStringInBracket(name+i2,sourceOfParams+i);
312 i2+=i3-1;
313 i+=i3-1;
314 continue;
315 }
316 if(!IsVariableChar(sourceOfParams[i])){
317 name[i2]=0;
318 break;
319 }
320 name[i2]=sourceOfParams[i];
321 }
322 if(sw){
323 //配列パラメータ
324 if( isRef == false ) compiler.errorMessenger.Output(29,NULL,nowLine);
325 isArray = true;
326
327 if((name[i2-2]=='('&&name[i2-1]==')')||
328 (name[i2-2]=='['&&name[i2-1]==']'))
329 {
330 subscripts.push_back( LONG_MAX );
331
332 name[i2-2]=0;
333 }
334 else{
335 GetArrange(name,temp2,subscripts);
336 lstrcpy(name,temp2);
337 }
338
339 i2=lstrlen(name);
340 }
341
342 //型
343 Type type( DEF_NON );
344 if(lstrcmp(name,"...")==0) type.SetBasicType( DEF_ELLIPSE );
345 else if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_AS){
346 i+=2;
347
348 i2=0;
349 while(sourceOfParams[i]=='*'){
350 temporary[i2]=sourceOfParams[i];
351 i++;
352 i2++;
353 }
354 for(;;i++,i2++){
355 if(!IsVariableChar(sourceOfParams[i])){
356 if(sourceOfParams[i]==1&&(sourceOfParams[i+1]==ESC_FUNCTION||sourceOfParams[i+1]==ESC_SUB)){
357 temporary[i2++]=sourceOfParams[i++];
358 temporary[i2]=sourceOfParams[i];
359 continue;
360 }
361 temporary[i2]=0;
362 break;
363 }
364 temporary[i2]=sourceOfParams[i];
365 }
366
367 compiler.StringToType( temporary, type );
368
369 if( type.IsNull() ){
370 compiler.errorMessenger.Output(3,temporary,nowLine);
371 type.SetBasicType( DEF_PTR_VOID );
372 }
373 }
374 else{
375 type.SetBasicType( Type::GetBasicTypeFromSimpleName(temporary) );
376 compiler.errorMessenger.Output(-103,temporary,nowLine);
377 }
378
379 Parameter *pParam = new Parameter( name, type, isRef );
380 if( isArray ){
381 pParam->SetArray( subscripts );
382 }
383
384 //パラメータを追加
385 this->params.push_back( pParam );
386
387 if(sourceOfParams[i]==','){
388 i++;
389 continue;
390 }
391 else if(sourceOfParams[i]==')') continue;
392 else{
393 compiler.errorMessenger.Output(1,NULL,nowLine);
394 break;
395 }
396 }
397 i++;
398
399 if(sourceOfParams[i]){
400 ///////////////////
401 // 戻り値を取得
402 ///////////////////
403
404 i2=lstrlen(sourceOfParams)-2;
405
406 int sw_as=0;
407 for(;i2>0;i2--){
408 if(sourceOfParams[i2]==')') break;
409
410 if(sourceOfParams[i2]==1&&sourceOfParams[i2+1]==ESC_AS){
411 i2+=2;
412 i3=0;
413 while(sourceOfParams[i2]=='*') temporary[i3++]=sourceOfParams[i2++];
414 for(;;i2++,i3++){
415 if(!IsVariableChar(sourceOfParams[i2])){
416 temporary[i3]=0;
417 break;
418 }
419 temporary[i3]=sourceOfParams[i2];
420 }
421 compiler.StringToType( temporary, this->returnType );
422 if( this->returnType.IsNull() ) compiler.errorMessenger.Output(3,temporary,nowLine);
423
424 sw_as=1;
425 break;
426 }
427 }
428 }
429 else{
430 //戻り値なしのSub定義
431 this->returnType.SetNull();
432 }
433
434 return true;
435}
436
437void DllProcs::Add(const NamespaceScopes &namespaceScopes, char *buffer,int nowLine){
438 int i2;
439
440 int i=0;
441
442 //Sub/Function
443 Procedure::Kind kind = Procedure::Sub;
444 if(buffer[i]==ESC_SUB){
445 }
446 else if(buffer[i]==ESC_FUNCTION){
447 kind = Procedure::Function;
448 }
449 else{
450 compiler.errorMessenger.Output(1,NULL,nowLine);
451 return;
452 }
453 i++;
454
455 //プロシージャ名
456 char procName[VN_SIZE];
457 bool isCdecl = false;
458 for(i2=0;;i++,i2++){
459 if(buffer[i]==1&&buffer[i+1]==ESC_CDECL){
460 isCdecl = true;
461
462 i+=2;
463 procName[i2]=0;
464 break;
465 }
466 if(buffer[i]==','){
467 procName[i2]=0;
468 break;
469 }
470 if(buffer[i]=='\0'){
471 compiler.errorMessenger.Output(1,NULL,nowLine);
472 return;
473 }
474 procName[i2]=buffer[i];
475 }
476 i++;
477
478 //ユーザー定義関数との重複チェック
479 if(GetSubHash(procName)){
480 compiler.errorMessenger.Output(15,procName,nowLine);
481 return;
482 }
483
484
485 //ライブラリ
486 char dllFileName[MAX_PATH];
487 i = GetOneParameter( buffer, i, dllFileName );
488 Type resultType;
489 _int64 i64data;
490 if( !StaticCalculation( true, dllFileName, 0, &i64data, resultType ) ){
491 return;
492 }
493 if( resultType.GetBasicType() != typeOfPtrChar ){
494 compiler.errorMessenger.Output(1,NULL,nowLine);
495 return;
496 }
497 lstrcpy( dllFileName, (char *)i64data );
498 CharUpper(dllFileName);
499 if(!strstr(dllFileName,".")){
500 lstrcat(dllFileName,".DLL");
501 if(lstrlen(dllFileName)>=16){
502 compiler.errorMessenger.Output(7,NULL,nowLine);
503 return;
504 }
505 }
506
507 //エイリアス
508 char alias[VN_SIZE];
509 i = GetOneParameter( buffer, i, alias );
510 if( alias[0] ){
511 if( !StaticCalculation( true, alias, 0, &i64data, resultType ) ){
512 return;
513 }
514 if( resultType.GetBasicType() != typeOfPtrChar ){
515 compiler.errorMessenger.Output(1,NULL,nowLine);
516 return;
517 }
518 lstrcpy( alias, (char *)i64data );
519 }
520 else{
521 //省略されたときは関数名
522 lstrcpy( alias, procName );
523 }
524
525
526 // オブジェクトを生成
527 DllProc *pDllProc = new DllProc( namespaceScopes, procName, kind, isCdecl, dllFileName, alias );
528
529 // パラメータを解析
530 // ※第1パラメータにに指定するデータの例:"( s As String ) As String"
531 pDllProc->SetParamsAndReturnType( buffer + i, nowLine );
532
533 // パラメータのエラーチェック
534 BOOST_FOREACH( const Parameter *pParam, pDllProc->Params() ){
535 if( pParam->IsObject() ){
536 compiler.errorMessenger.Output(25,pParam->GetVarName(),nowLine);
537 }
538 if( !pParam->IsRef() ){
539 if( pParam->IsStruct() ){
540 compiler.errorMessenger.Output(28,pParam->GetVarName(),nowLine);
541 }
542 }
543 }
544
545 //戻り値のエラーチェック
546 if( pDllProc->IsFunction() ){
547 // Function定義
548
549 if( pDllProc->ReturnType().IsObject() ){
550 // DLL関数ではオブジェクトを戻り値にできない
551 compiler.errorMessenger.Output(40,pDllProc->GetName(),nowLine);
552 }
553 }
554
555 // ハッシュマップに追加
556 this->Put( pDllProc );
557}
558
559bool ProcPointer::SetParamsAndReturnType( const char *sourceOfParams, int nowLine ){
560 int i = 0;
561 int i2,i3,sw;
562 char temporary[8192],temp2[VN_SIZE];
563
564 //ソースコードの位置
565 this->codePos = nowLine;
566
567 //パラメータ
568 if(sourceOfParams[i]!='('){
569 compiler.errorMessenger.Output(1,NULL,nowLine);
570 return 0;
571 }
572 i++;
573 while(1){
574 if(sourceOfParams[i]==')') break;
575
576 //ByRef
577 bool isRef;
578 if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_BYVAL){
579 isRef = false;
580 i+=2;
581 }
582 else if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_BYREF){
583 isRef = true;
584 i+=2;
585 }
586 else isRef = false;
587
588 //パラメータ名
589 bool isArray = false;
590 Subscripts subscripts;
591 char name[VN_SIZE];
592 sw=0;
593 for(i2=0;;i++,i2++){
594 if(sourceOfParams[i]=='('){
595 if(!sw) sw=1;
596
597 i3=GetStringInPare(name+i2,sourceOfParams+i);
598 i2+=i3-1;
599 i+=i3-1;
600 continue;
601 }
602 if(sourceOfParams[i]=='['){
603 if(!sw) sw=1;
604
605 i3=GetStringInBracket(name+i2,sourceOfParams+i);
606 i2+=i3-1;
607 i+=i3-1;
608 continue;
609 }
610 if(!IsVariableChar(sourceOfParams[i])){
611 name[i2]=0;
612 break;
613 }
614 name[i2]=sourceOfParams[i];
615 }
616 if(sw){
617 //配列パラメータ
618 if( isRef == false ) compiler.errorMessenger.Output(29,NULL,nowLine);
619 isArray = true;
620
621 if((name[i2-2]=='('&&name[i2-1]==')')||
622 (name[i2-2]=='['&&name[i2-1]==']'))
623 {
624 subscripts.push_back( LONG_MAX );
625
626 name[i2-2]=0;
627 }
628 else{
629 GetArrange(name,temp2,subscripts);
630 lstrcpy(name,temp2);
631 }
632
633 i2=lstrlen(name);
634 }
635
636 //型
637 Type type( DEF_NON );
638 if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_AS){
639 i+=2;
640
641 i2=0;
642 while(sourceOfParams[i]=='*'){
643 temporary[i2]=sourceOfParams[i];
644 i++;
645 i2++;
646 }
647 for(;;i++,i2++){
648 if(!IsVariableChar(sourceOfParams[i])){
649 if(sourceOfParams[i]==1&&(sourceOfParams[i+1]==ESC_FUNCTION||sourceOfParams[i+1]==ESC_SUB)){
650 temporary[i2++]=sourceOfParams[i++];
651 temporary[i2]=sourceOfParams[i];
652 continue;
653 }
654 temporary[i2]=0;
655 break;
656 }
657 temporary[i2]=sourceOfParams[i];
658 }
659
660 compiler.StringToType( temporary, type );
661
662 if( type.IsNull() ){
663 compiler.errorMessenger.Output(3,temporary,nowLine);
664 type.SetBasicType( DEF_PTR_VOID );
665 }
666 }
667 else{
668 type.SetBasicType( Type::GetBasicTypeFromSimpleName(temporary) );
669 compiler.errorMessenger.Output(-103,temporary,nowLine);
670 }
671
672 Parameter *pParam = new Parameter( name, type, isRef );
673 if( isArray ){
674 pParam->SetArray( subscripts );
675 }
676
677 //パラメータを追加
678 this->params.push_back( pParam );
679
680 if(sourceOfParams[i]==','){
681 i++;
682 continue;
683 }
684 else if(sourceOfParams[i]==')') continue;
685 else{
686 compiler.errorMessenger.Output(1,NULL,nowLine);
687 break;
688 }
689 }
690 i++;
691
692 if(sourceOfParams[i]){
693 ///////////////////
694 // 戻り値を取得
695 ///////////////////
696
697 i2=lstrlen(sourceOfParams)-2;
698
699 int sw_as=0;
700 for(;i2>0;i2--){
701 if(sourceOfParams[i2]==')') break;
702
703 if(sourceOfParams[i2]==1&&sourceOfParams[i2+1]==ESC_AS){
704 i2+=2;
705 i3=0;
706 while(sourceOfParams[i2]=='*') temporary[i3++]=sourceOfParams[i2++];
707 for(;;i2++,i3++){
708 if(!IsVariableChar(sourceOfParams[i2])){
709 temporary[i3]=0;
710 break;
711 }
712 temporary[i3]=sourceOfParams[i2];
713 }
714 compiler.StringToType( temporary, this->returnType );
715 if( this->returnType.IsNull() ) compiler.errorMessenger.Output(3,temporary,nowLine);
716
717 sw_as=1;
718 break;
719 }
720 }
721 }
722 else{
723 //戻り値なしのSub定義
724 this->returnType.SetNull();
725 }
726
727 //戻り値のエラーチェック
728 if( IsFunction() ){
729 // Function定義
730
731 if( this->ReturnType().IsNull() ){
732 // 戻り値がない
733 compiler.errorMessenger.Output(26,this->GetName(),nowLine);
734 }
735 }
736 else{
737 if( !this->ReturnType().IsNull() ){
738 // Sub定義なのに、戻り値がある
739 compiler.errorMessenger.Output(38,this->GetName(),nowLine);
740 }
741 }
742
743 return true;
744}
745
746int ProcPointers::Add( const std::string &typeExpression )
747{
748 DWORD dwProcType = (DWORD)typeExpression[2];
749 const std::string &paramStr = typeExpression.substr( 3 );
750
751 Procedure::Kind kind = Procedure::Sub;
752 if( dwProcType == ESC_FUNCTION ){
753 kind = Procedure::Function;
754 }
755
756 ProcPointer *pProcPointer = new ProcPointer( kind );
757
758 //buffer[0]は'('となっている
759 extern int cp;
760 pProcPointer->SetParamsAndReturnType( paramStr.c_str(), cp );
761
762 this->push_back( pProcPointer );
763
764 return (int)this->size()-1;
765}
766
767void ProcPointers::Clear()
768{
769 ProcPointers &procPointers = *this;
770 BOOST_FOREACH( ProcPointer *pProcPointer, procPointers ){
771 delete pProcPointer;
772 }
773 this->clear();
774}
Note: See TracBrowser for help on using the repository browser.