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, 15 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.