source: dev/trunk/abdev/BasicCompiler_Common/src/Procedure.cpp @ 350

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

インターフェイスを実装

File size: 24.1 KB
Line 
1#include "stdafx.h"
2
3#include <jenga/include/smoothie/Smoothie.h>
4#include <jenga/include/smoothie/SmoothieException.h>
5#include <jenga/include/smoothie/LexicalAnalysis.h>
6
7#include <Compiler.h>
8#include <Procedure.h>
9#include <NamespaceSupporter.h>
10
11#include "../common.h"
12#ifdef _AMD64_
13#include "../../BasicCompiler64/opcode.h"
14#else
15#include "../../BasicCompiler32/opcode.h"
16#endif
17
18
19std::string UserProc::GetFullName() const
20{
21    if( HasParentClass() ){
22        return GetParentClass().GetName() + "." + GetName();
23    }
24
25    return GetName();
26}
27bool UserProc::IsCastOperator() const
28{
29    if( GetName()[0] == 1 && GetName()[1] == ESC_OPERATOR && GetName()[2] == CALC_AS )
30    {
31        return true;
32    }
33    return false;
34}
35const NamespaceScopes &UserProc::GetNamespaceScopes() const
36{
37    if( HasParentClass() ){
38        return GetParentClassPtr()->GetNamespaceScopes();
39    }
40    return Symbol::GetNamespaceScopes();
41}
42const NamespaceScopesCollection &UserProc::GetImportedNamespaces() const
43{
44    if( pParentClass )
45    {
46        return pParentClass->GetImportedNamespaces();
47    }
48    return importedNamespaces;
49}
50bool UserProc::IsVirtual() const
51{
52    if( pMethod == NULL ){
53        return false;
54    }
55    return ( pMethod->IsVirtual() != 0 );
56}
57const CMethod &UserProc::GetMethod() const
58{
59    if( !HasParentClass() )
60    {
61        Jenga::Throw( "グローバル関数に対してUserProc::GetMethodメソッドが呼ばれた" );
62    }
63    return *pMethod;
64}
65
66bool UserProc::SetParamsAndReturnType( const char *sourceOfParams, int nowLine, bool isStatic ){
67    int i = 0;
68    int i2,i3,sw;
69    char temporary[8192],temp2[VN_SIZE];
70
71    //ソースコードの位置
72    this->codePos = nowLine;
73
74    //パラメータ
75    if(sourceOfParams[i]!='('){
76        SmoothieException::Throw(1,NULL,nowLine);
77        return 0;
78    }
79    i++;
80    if(sourceOfParams[i]!=')'&& this->pParentClass ){
81        //クラスのメンバ関数の場合のみ、デストラクタにパラメータがある場合にエラーをだす
82        if(this->GetName()[0]=='~'){
83            SmoothieException::Throw(114,NULL,nowLine);
84            i=JumpStringInPare(sourceOfParams,i);
85        }
86    }
87    while(1){
88        if(sourceOfParams[i]==')') break;
89
90        //ByRef
91        bool isRef;
92        if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_BYVAL){
93            isRef = false;
94            i+=2;
95        }
96        else if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_BYREF){
97            isRef = true;
98            i+=2;
99        }
100        else isRef = false;
101
102        //パラメータ名
103        bool isArray = false;
104        Subscripts subscripts;
105        char name[VN_SIZE];
106        sw=0;
107        for(i2=0;;i++,i2++){
108            if(sourceOfParams[i]=='('){
109                if(!sw) sw=1;
110
111                i3=GetStringInPare(name+i2,sourceOfParams+i);
112                i2+=i3-1;
113                i+=i3-1;
114                continue;
115            }
116            if(sourceOfParams[i]=='['){
117                if(!sw) sw=1;
118
119                i3=GetStringInBracket(name+i2,sourceOfParams+i);
120                i2+=i3-1;
121                i+=i3-1;
122                continue;
123            }
124            if(!IsVariableChar(sourceOfParams[i])){
125                name[i2]=0;
126                break;
127            }
128            name[i2]=sourceOfParams[i];
129        }
130        if(sw){
131            //配列パラメータ
132            if( isRef == false ) SmoothieException::Throw(29,NULL,nowLine);
133            isArray = true;
134
135            if((name[i2-2]=='('&&name[i2-1]==')')||
136                (name[i2-2]=='['&&name[i2-1]==']'))
137            {
138                subscripts.push_back( LONG_MAX );
139
140                name[i2-2]=0;
141            }
142            else{
143                GetArrange(name,temp2,subscripts);
144                lstrcpy(name,temp2);
145            }
146
147            i2=lstrlen(name);
148        }
149
150        Type type( DEF_NON );
151        char initValue[8192] = "";
152        if( sourceOfParams[i] == '=' ){
153            i++;
154            i = GetOneParameter( sourceOfParams, i, initValue );
155
156            // TODO: エラー用 fix me!!!
157            //cp = nowLine;
158
159            NumOpe_GetType( initValue, GetStringTypeInfo(), type );
160           
161            if( IS_LITERAL(type.GetIndex()) )
162            {
163                type.SetIndex( -1 );
164            }
165        }
166        else if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_AS){
167            // As指定
168            i+=2;
169
170            i2=0;
171            while(sourceOfParams[i]=='*'){
172                temporary[i2]=sourceOfParams[i];
173                i++;
174                i2++;
175            }
176            for(;;i++,i2++){
177                if(!IsVariableChar(sourceOfParams[i])){
178                    if(sourceOfParams[i]==1&&(sourceOfParams[i+1]==ESC_FUNCTION||sourceOfParams[i+1]==ESC_SUB)){
179                        temporary[i2++]=sourceOfParams[i++];
180                        temporary[i2]=sourceOfParams[i];
181                        continue;
182                    }
183                    temporary[i2]=0;
184                    break;
185                }
186                temporary[i2]=sourceOfParams[i];
187            }
188
189            compiler.StringToType( temporary, type );
190
191            if( type.IsNull() ){
192                SmoothieException::Throw(3,temporary,nowLine);
193                type.SetBasicType( DEF_PTR_VOID );
194            }
195
196            if( type.IsObject() ){
197                if( type.GetClass().IsBlittableType() ){
198                    // Blittable型のときは基本型として扱う
199                    type = type.GetClass().GetBlittableType();
200                }
201            }
202        }
203        else{
204            type.SetBasicType( Type::GetBasicTypeFromSimpleName(temporary) );
205            SmoothieException::Throw(-103,temporary,nowLine);
206        }
207
208        Parameter *pParam = new Parameter( name, type, isRef, initValue );
209        if( isArray ){
210            pParam->SetArray( subscripts );
211        }
212
213        //パラメータを追加
214        this->params.push_back( pParam );
215
216        if(sourceOfParams[i]==','){
217            i++;
218            continue;
219        }
220        else if(sourceOfParams[i]==')') continue;
221        else{
222            SmoothieException::Throw(1,NULL,nowLine);
223            break;
224        }
225    }
226    this->secondParmNum = (int)this->params.size();
227    i++;
228    if(sourceOfParams[i]=='('){
229        i++;
230        while(1){
231            if(sourceOfParams[i]==')') break;
232
233            //ByRef
234            bool isRef;
235            if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_BYVAL){
236                isRef = false;
237                i+=2;
238            }
239            else if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_BYREF){
240                isRef = true;
241                i+=2;
242            }
243            else isRef = false;
244
245            //パラメータ名
246            bool isArray = false;
247            Subscripts subscripts;
248            char name[VN_SIZE];
249            sw=0;
250            for(i2=0;;i++,i2++){
251                if(sourceOfParams[i]=='('){
252                    if(!sw) sw=1;
253
254                    i3=GetStringInPare(name+i2,sourceOfParams+i);
255                    i2+=i3-1;
256                    i+=i3-1;
257                    continue;
258                }
259                if(sourceOfParams[i]=='['){
260                    if(!sw) sw=1;
261
262                    i3=GetStringInBracket(name+i2,sourceOfParams+i);
263                    i2+=i3-1;
264                    i+=i3-1;
265                    continue;
266                }
267                if(!IsVariableChar(sourceOfParams[i])){
268                    name[i2]=0;
269                    break;
270                }
271                name[i2]=sourceOfParams[i];
272            }
273            if(sw){
274                //配列パラメータ
275                if( isRef == false ) SmoothieException::Throw(29,NULL,nowLine);
276                isArray = true;
277
278                if((name[i2-2]=='('&&name[i2-1]==')')||
279                    (name[i2-2]=='['&&name[i2-1]==']'))
280                {
281                    subscripts.push_back( LONG_MAX );
282
283                    name[i2-2]=0;
284                }
285                else{
286                    GetArrange(name,temp2,subscripts);
287                    lstrcpy(name,temp2);
288                }
289
290                i2=lstrlen(name);
291            }
292
293            //型
294            Type type( DEF_NON );
295            if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_AS){
296                i+=2;
297
298                i2=0;
299                while(sourceOfParams[i]=='*'){
300                    temporary[i2]=sourceOfParams[i];
301                    i++;
302                    i2++;
303                }
304                for(;;i++,i2++){
305                    if(!IsVariableChar(sourceOfParams[i])){
306                        if(sourceOfParams[i]==1&&(sourceOfParams[i+1]==ESC_FUNCTION||sourceOfParams[i+1]==ESC_SUB)){
307                            temporary[i2++]=sourceOfParams[i++];
308                            temporary[i2]=sourceOfParams[i];
309                            continue;
310                        }
311                        temporary[i2]=0;
312                        break;
313                    }
314                    temporary[i2]=sourceOfParams[i];
315                }
316
317                compiler.StringToType( temporary, type );
318
319                if( type.IsNull() ){
320                    SmoothieException::Throw(3,temporary,nowLine);
321                    type.SetBasicType( DEF_PTR_VOID );
322                }
323            }
324            else{
325                type.SetBasicType( Type::GetBasicTypeFromSimpleName(temporary) );
326                SmoothieException::Throw(-103,temporary,nowLine);
327            }
328
329            Parameter *pParam = new Parameter( name, type, isRef );
330            if( isArray ){
331                pParam->SetArray( subscripts );
332            }
333
334            //パラメータを追加
335            this->params.push_back( pParam );
336
337            if(sourceOfParams[i]==','){
338                i++;
339                continue;
340            }
341            else if(sourceOfParams[i]==')') continue;
342            else{
343                SmoothieException::Throw(1,NULL,nowLine);
344                break;
345            }
346        }
347        i++;
348    }
349
350    if(sourceOfParams[i]){
351        ///////////////////
352        // 戻り値を取得
353        ///////////////////
354
355        if( !this->IsFunction() ){
356            // Sub/Macroの場合
357            SmoothieException::Throw(38,this->GetName(),nowLine);
358        }
359
360        if( this->pParentClass ){
361            if( this->GetName() == this->pParentClass->GetName() ||
362                this->GetName()[0]=='~'){
363                //クラスのコンストラクタ、デストラクタがFunction定義の場合はエラーをだす
364                SmoothieException::Throw(115,NULL,nowLine);
365            }
366        }
367
368
369        i2=lstrlen(sourceOfParams)-2;
370
371        int sw_as=0;
372        for(;i2>0;i2--){
373            if(sourceOfParams[i2]==')') break;
374
375            if(sourceOfParams[i2]==1&&sourceOfParams[i2+1]==ESC_AS){
376                i2+=2;
377                i3=0;
378                while(sourceOfParams[i2]=='*') temporary[i3++]=sourceOfParams[i2++];
379                for(;;i2++,i3++){
380                    if( IsCommandDelimitation( sourceOfParams[i2] ) )
381                    {
382                        temporary[i3]=0;
383                        break;
384                    }
385                    temporary[i3]=sourceOfParams[i2];
386                }
387                compiler.StringToType( temporary, this->returnType );
388                if( this->returnType.IsNull() ) SmoothieException::Throw(3,temporary,nowLine);
389
390                sw_as=1;
391                break;
392            }
393        }
394
395        if(!sw_as){
396            SmoothieException::Throw(-104,this->GetName().c_str(),nowLine);
397
398            this->returnType.SetBasicType( DEF_DOUBLE );
399        }
400    }
401    else{
402        //戻り値なしのSub定義
403        this->returnType.SetNull();
404    }
405
406    //リアルパラメータ領域を取得(_System_LocalThisを考慮して2つだけ多く確保する場合がある)
407
408    if( this->pParentClass && isStatic == false ){
409        //オブジェクトメンバの場合は、第一パラメータを_System_LocalThis引き渡し用として利用
410        string name = "_System_LocalThis";
411        Type type( DEF_PTR_VOID );
412        this->realParams.push_back( new Parameter( name, type ) );
413    }
414
415    if( this->returnType.IsStruct() ){
416        //構造体を戻り値として持つ場合
417        //※第一パラメータ(Thisポインタありの場合は第二パラメータ)を戻り値用の参照宣言にする
418
419        string name = this->GetName();
420        if(name[0]==1&&name[1]==ESC_OPERATOR){
421            name="_System_ReturnValue";
422        }
423        Type type( DEF_STRUCT, this->returnType.GetIndex() );
424        this->realParams.push_back( new Parameter( name, type, true ) );
425    }
426
427    //パラメータをコピー
428    BOOST_FOREACH( Parameter *pParam, params ){
429        this->realParams.push_back( new Parameter( *pParam ) );
430    }
431
432    return true;
433}
434
435const UserProc *UserProc::pCompilingUserProc = NULL;
436
437
438bool UserProcs::Insert( UserProc *pUserProc, int nowLine )
439{
440    /////////////////////////////////
441    // ハッシュデータに追加
442    /////////////////////////////////
443
444    if( !Put( pUserProc ) )
445    {
446        // 重複しているため、失敗
447        SetError(15,pUserProc->GetName().c_str(),nowLine);
448        return false;
449    }
450
451    return true;
452}
453UserProc *UserProcs::Add( const NamespaceScopes &namespaceScopes, const NamespaceScopesCollection &importedNamespaces, char *buffer,int nowLine,bool isVirtual,CClass *pobj_c, bool isStatic)
454{
455    int i2,i3;
456    char temporary[8192];
457
458    int i=1;
459
460    Procedure::Kind kind = Procedure::Sub;
461    bool isMacro = false;
462    if(buffer[i]==ESC_FUNCTION) kind = Procedure::Function;
463    if(buffer[i]==ESC_MACRO){
464        isMacro = true;
465    }
466
467    i++;
468
469    bool isCdecl = false;
470    bool isExport = false;
471    while(1){
472        if(buffer[i]==1&&buffer[i+1]==ESC_CDECL&& isCdecl == false ){
473            isCdecl = true;
474
475            i+=2;
476        }
477        else if(buffer[i]==1&&buffer[i+1]==ESC_EXPORT&& isExport == false ){
478            isExport = true;
479
480            i+=2;
481        }
482        else break;
483    }
484
485    i2=0;
486    if(buffer[i]==1&&buffer[i+1]==ESC_OPERATOR){
487        if(!pobj_c){
488            SetError(126,NULL,nowLine);
489            return 0;
490        }
491
492        //オペレータの場合
493        temporary[i2++]=buffer[i++];
494        temporary[i2++]=buffer[i++];
495
496        int iCalcId;
497        if(buffer[i]=='='&&buffer[i+1]=='='){
498            iCalcId=CALC_EQUAL;
499            i3=2;
500        }
501        else if(buffer[i]=='='){
502            iCalcId=CALC_SUBSITUATION;
503            i3=1;
504        }
505        else if(buffer[i]=='('){
506            iCalcId=CALC_AS;
507            i3=0;
508        }
509        else if(buffer[i]=='['&&buffer[i+1]==']'&&buffer[i+2]=='='){
510            iCalcId=CALC_ARRAY_SET;
511            i3=3;
512        }
513        else if(buffer[i]=='['&&buffer[i+1]==']'){
514            iCalcId=CALC_ARRAY_GET;
515            i3=2;
516        }
517        else{
518            iCalcId=GetCalcId(buffer+i,&i3);
519            i3++;
520        }
521        if(!iCalcId){
522            SetError(1,NULL,nowLine);
523            return 0;
524        }
525        temporary[i2++]=iCalcId;
526        temporary[i2]=0;
527
528        i+=i3;
529    }
530    else{
531        if(pobj_c){
532            //クラスメンバの場合、デストラクタには~が付くことを考慮
533            if(buffer[i]=='~'){
534                temporary[i2]='~';
535                i++;
536                i2++;
537            }
538        }
539
540        for(;;i++,i2++){
541            if(!IsVariableChar(buffer[i])){
542                temporary[i2]=0;
543                break;
544            }
545            temporary[i2]=buffer[i];
546        }
547    }
548
549    if( isMacro ){
550        //大文字に変換
551        CharUpper(temporary);
552
553        //マクロ関数の場合は名前リストに追加
554        macroNames.push_back( temporary );
555    }
556
557    if(!pobj_c){
558        //クラスメンバ以外の場合のみ
559        //重複チェック
560
561        if(GetDeclareHash(temporary)){
562            SetError(15,temporary,nowLine);
563            return 0;
564        }
565    }
566
567    // 識別ID
568    static int id_base=0;
569
570    UserProc *pUserProc = new UserProc( namespaceScopes, importedNamespaces, temporary, kind, isMacro, isCdecl, isExport, (id_base++) );
571    pUserProc->SetParentClass( pobj_c );
572    if( Smoothie::isFullCompile ){
573        // すべての関数・メソッドをコンパイルする
574        pUserProc->Using();
575    }
576
577    if(isExport){
578        pUserProc->Using();
579    }
580
581    // パラメータを解析
582    // ※第1パラメータにに指定するデータの例:"( s As String ) As String"
583    pUserProc->SetParamsAndReturnType( buffer + i, nowLine, isStatic );
584
585    pUserProc->_paramStr = buffer + i;
586
587    // ハッシュに追加
588    if( !Insert( pUserProc, nowLine ) )
589    {
590        return NULL;
591    }
592
593    return pUserProc;
594}
595void UserProcs::EnumGlobalProcs( const char *simpleName, const char *localName, std::vector<const UserProc *> &subs )
596{
597    ///////////////////////////
598    // グローバル関数を検索
599    ///////////////////////////
600
601    // ハッシュ値を取得
602    UserProc *pUserProc = GetHashArrayElement( simpleName );
603    while(pUserProc){
604        if( pUserProc->IsGlobalProcedure() ){
605            if( pUserProc->IsEqualSymbol( localName ) ){
606                subs.push_back( pUserProc );
607            }
608        }
609
610        pUserProc=pUserProc->GetChainNext();
611    }
612}
613
614bool DllProc::SetParamsAndReturnType( const char *sourceOfParams, int nowLine ){
615    int i = 0;
616    int i2,i3,sw;
617    char temporary[8192],temp2[VN_SIZE];
618
619    //ソースコードの位置
620    this->codePos = nowLine;
621
622    //パラメータ
623    if(sourceOfParams[i]!='('){
624        SmoothieException::Throw(1,NULL,nowLine);
625        return 0;
626    }
627    i++;
628
629    while(1){
630        if(sourceOfParams[i]==')') break;
631
632        //ByRef
633        bool isRef;
634        if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_BYVAL){
635            isRef = false;
636            i+=2;
637        }
638        else if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_BYREF){
639            isRef = true;
640            i+=2;
641        }
642        else isRef = false;
643
644        //パラメータ名
645        bool isArray = false;
646        Subscripts subscripts;
647        char name[VN_SIZE];
648        sw=0;
649        for(i2=0;;i++,i2++){
650            if(sourceOfParams[i]=='('){
651                if(!sw) sw=1;
652
653                i3=GetStringInPare(name+i2,sourceOfParams+i);
654                i2+=i3-1;
655                i+=i3-1;
656                continue;
657            }
658            if(sourceOfParams[i]=='['){
659                if(!sw) sw=1;
660
661                i3=GetStringInBracket(name+i2,sourceOfParams+i);
662                i2+=i3-1;
663                i+=i3-1;
664                continue;
665            }
666            if(!IsVariableChar(sourceOfParams[i])){
667                name[i2]=0;
668                break;
669            }
670            name[i2]=sourceOfParams[i];
671        }
672        if(sw){
673            //配列パラメータ
674            if( isRef == false ) SmoothieException::Throw(29,NULL,nowLine);
675            isArray = true;
676
677            if((name[i2-2]=='('&&name[i2-1]==')')||
678                (name[i2-2]=='['&&name[i2-1]==']'))
679            {
680                subscripts.push_back( LONG_MAX );
681
682                name[i2-2]=0;
683            }
684            else{
685                GetArrange(name,temp2,subscripts);
686                lstrcpy(name,temp2);
687            }
688
689            i2=lstrlen(name);
690        }
691
692        //型
693        Type type( DEF_NON );
694        if(lstrcmp(name,"...")==0) type.SetBasicType( DEF_ELLIPSE );
695        else if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_AS){
696            i+=2;
697
698            i2=0;
699            while(sourceOfParams[i]=='*'){
700                temporary[i2]=sourceOfParams[i];
701                i++;
702                i2++;
703            }
704            for(;;i++,i2++){
705                if(!IsVariableChar(sourceOfParams[i])){
706                    if(sourceOfParams[i]==1&&(sourceOfParams[i+1]==ESC_FUNCTION||sourceOfParams[i+1]==ESC_SUB)){
707                        temporary[i2++]=sourceOfParams[i++];
708                        temporary[i2]=sourceOfParams[i];
709                        continue;
710                    }
711                    temporary[i2]=0;
712                    break;
713                }
714                temporary[i2]=sourceOfParams[i];
715            }
716
717            compiler.StringToType( temporary, type );
718
719            if( type.IsNull() ){
720                SmoothieException::Throw(3,temporary,nowLine);
721                type.SetBasicType( DEF_PTR_VOID );
722            }
723        }
724        else{
725            type.SetBasicType( Type::GetBasicTypeFromSimpleName(temporary) );
726            SmoothieException::Throw(-103,temporary,nowLine);
727        }
728
729        Parameter *pParam = new Parameter( name, type, isRef );
730        if( isArray ){
731            pParam->SetArray( subscripts );
732        }
733
734        //パラメータを追加
735        this->params.push_back( pParam );
736
737        if(sourceOfParams[i]==','){
738            i++;
739            continue;
740        }
741        else if(sourceOfParams[i]==')') continue;
742        else{
743            SmoothieException::Throw(1,NULL,nowLine);
744            break;
745        }
746    }
747    i++;
748
749    if(sourceOfParams[i]){
750        ///////////////////
751        // 戻り値を取得
752        ///////////////////
753
754        i2=lstrlen(sourceOfParams)-2;
755
756        int sw_as=0;
757        for(;i2>0;i2--){
758            if(sourceOfParams[i2]==')') break;
759
760            if(sourceOfParams[i2]==1&&sourceOfParams[i2+1]==ESC_AS){
761                i2+=2;
762                i3=0;
763                while(sourceOfParams[i2]=='*') temporary[i3++]=sourceOfParams[i2++];
764                for(;;i2++,i3++){
765                    if(!IsVariableChar(sourceOfParams[i2])){
766                        temporary[i3]=0;
767                        break;
768                    }
769                    temporary[i3]=sourceOfParams[i2];
770                }
771                compiler.StringToType( temporary, this->returnType );
772                if( this->returnType.IsNull() ) SmoothieException::Throw(3,temporary,nowLine);
773
774                sw_as=1;
775                break;
776            }
777        }
778    }
779    else{
780        //戻り値なしのSub定義
781        this->returnType.SetNull();
782    }
783
784    return true;
785}
786
787void DllProcs::Add(const NamespaceScopes &namespaceScopes, char *buffer,int nowLine){
788    int i2;
789
790    int i=0;
791
792    //Sub/Function
793    Procedure::Kind kind = Procedure::Sub;
794    if(buffer[i]==ESC_SUB){
795    }
796    else if(buffer[i]==ESC_FUNCTION){
797        kind = Procedure::Function;
798    }
799    else{
800        SetError(1,NULL,nowLine);
801        return;
802    }
803    i++;
804
805    //プロシージャ名
806    char procName[VN_SIZE];
807    bool isCdecl = false;
808    for(i2=0;;i++,i2++){
809        if(buffer[i]==1&&buffer[i+1]==ESC_CDECL){
810            isCdecl = true;
811
812            i+=2;
813            procName[i2]=0;
814            break;
815        }
816        if(buffer[i]==','){
817            procName[i2]=0;
818            break;
819        }
820        if(buffer[i]=='\0'){
821            SetError(1,NULL,nowLine);
822            return;
823        }
824        procName[i2]=buffer[i];
825    }
826    i++;
827
828    //ユーザー定義関数との重複チェック
829    if(GetSubHash(procName)){
830        SetError(15,procName,nowLine);
831        return;
832    }
833
834
835    //ライブラリ
836    char dllFileName[MAX_PATH];
837    i = GetOneParameter( buffer, i, dllFileName );
838    Type resultType;
839    _int64 i64data;
840    if( !StaticCalculation( true, dllFileName, 0, &i64data, resultType ) ){
841        return;
842    }
843    if( resultType.GetBasicType() != typeOfPtrChar ){
844        SetError(1,NULL,nowLine);
845        return;
846    }
847    lstrcpy( dllFileName, (char *)i64data );
848    CharUpper(dllFileName);
849    if(!strstr(dllFileName,".")){
850        lstrcat(dllFileName,".DLL");
851        if(lstrlen(dllFileName)>=16){
852            SetError(7,NULL,nowLine);
853            return;
854        }
855    }
856
857    //エイリアス
858    char alias[VN_SIZE];
859    i = GetOneParameter( buffer, i, alias );
860    if( alias[0] ){
861        if( !StaticCalculation( true, alias, 0, &i64data, resultType ) ){
862            return;
863        }
864        if( resultType.GetBasicType() != typeOfPtrChar ){
865            SetError(1,NULL,nowLine);
866            return;
867        }
868        lstrcpy( alias, (char *)i64data );
869    }
870    else{
871        //省略されたときは関数名
872        lstrcpy( alias, procName );
873    }
874
875
876    // オブジェクトを生成
877    DllProc *pDllProc = new DllProc( namespaceScopes, procName, kind, isCdecl, dllFileName, alias );
878
879    // パラメータを解析
880    // ※第1パラメータにに指定するデータの例:"( s As String ) As String"
881    pDllProc->SetParamsAndReturnType( buffer + i, nowLine );
882
883    // パラメータのエラーチェック
884    BOOST_FOREACH( const Parameter *pParam, pDllProc->Params() ){
885        if( pParam->IsObject() ){
886            SetError(25,pParam->GetVarName(),nowLine);
887        }
888        if( !pParam->IsRef() ){
889            if( pParam->IsStruct() ){
890                SetError(28,pParam->GetVarName(),nowLine);
891            }
892        }
893    }
894
895    //戻り値のエラーチェック
896    if( pDllProc->IsFunction() ){
897        // Function定義
898
899        if( pDllProc->ReturnType().IsObject() ){
900            // DLL関数ではオブジェクトを戻り値にできない
901            SetError(40,pDllProc->GetName(),nowLine);
902        }
903    }
904
905    // ハッシュマップに追加
906    this->Put( pDllProc );
907}
908
909bool ProcPointer::SetParamsAndReturnType( const char *sourceOfParams, int nowLine ){
910    int i = 0;
911    int i2,i3,sw;
912    char temporary[8192],temp2[VN_SIZE];
913
914    //ソースコードの位置
915    this->codePos = nowLine;
916
917    //パラメータ
918    if(sourceOfParams[i]!='('){
919        SmoothieException::Throw(1,NULL,nowLine);
920        return 0;
921    }
922    i++;
923    while(1){
924        if(sourceOfParams[i]==')') break;
925
926        //ByRef
927        bool isRef;
928        if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_BYVAL){
929            isRef = false;
930            i+=2;
931        }
932        else if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_BYREF){
933            isRef = true;
934            i+=2;
935        }
936        else isRef = false;
937
938        //パラメータ名
939        bool isArray = false;
940        Subscripts subscripts;
941        char name[VN_SIZE];
942        sw=0;
943        for(i2=0;;i++,i2++){
944            if(sourceOfParams[i]=='('){
945                if(!sw) sw=1;
946
947                i3=GetStringInPare(name+i2,sourceOfParams+i);
948                i2+=i3-1;
949                i+=i3-1;
950                continue;
951            }
952            if(sourceOfParams[i]=='['){
953                if(!sw) sw=1;
954
955                i3=GetStringInBracket(name+i2,sourceOfParams+i);
956                i2+=i3-1;
957                i+=i3-1;
958                continue;
959            }
960            if(!IsVariableChar(sourceOfParams[i])){
961                name[i2]=0;
962                break;
963            }
964            name[i2]=sourceOfParams[i];
965        }
966        if(sw){
967            //配列パラメータ
968            if( isRef == false ) SmoothieException::Throw(29,NULL,nowLine);
969            isArray = true;
970
971            if((name[i2-2]=='('&&name[i2-1]==')')||
972                (name[i2-2]=='['&&name[i2-1]==']'))
973            {
974                subscripts.push_back( LONG_MAX );
975
976                name[i2-2]=0;
977            }
978            else{
979                GetArrange(name,temp2,subscripts);
980                lstrcpy(name,temp2);
981            }
982
983            i2=lstrlen(name);
984        }
985
986        //型
987        Type type( DEF_NON );
988        if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_AS){
989            i+=2;
990
991            i2=0;
992            while(sourceOfParams[i]=='*'){
993                temporary[i2]=sourceOfParams[i];
994                i++;
995                i2++;
996            }
997            for(;;i++,i2++){
998                if(!IsVariableChar(sourceOfParams[i])){
999                    if(sourceOfParams[i]==1&&(sourceOfParams[i+1]==ESC_FUNCTION||sourceOfParams[i+1]==ESC_SUB)){
1000                        temporary[i2++]=sourceOfParams[i++];
1001                        temporary[i2]=sourceOfParams[i];
1002                        continue;
1003                    }
1004                    temporary[i2]=0;
1005                    break;
1006                }
1007                temporary[i2]=sourceOfParams[i];
1008            }
1009
1010            compiler.StringToType( temporary, type );
1011
1012            if( type.IsNull() ){
1013                SmoothieException::Throw(3,temporary,nowLine);
1014                type.SetBasicType( DEF_PTR_VOID );
1015            }
1016        }
1017        else{
1018            type.SetBasicType( Type::GetBasicTypeFromSimpleName(temporary) );
1019            SmoothieException::Throw(-103,temporary,nowLine);
1020        }
1021
1022        Parameter *pParam = new Parameter( name, type, isRef );
1023        if( isArray ){
1024            pParam->SetArray( subscripts );
1025        }
1026
1027        //パラメータを追加
1028        this->params.push_back( pParam );
1029
1030        if(sourceOfParams[i]==','){
1031            i++;
1032            continue;
1033        }
1034        else if(sourceOfParams[i]==')') continue;
1035        else{
1036            SmoothieException::Throw(1,NULL,nowLine);
1037            break;
1038        }
1039    }
1040    i++;
1041
1042    if(sourceOfParams[i]){
1043        ///////////////////
1044        // 戻り値を取得
1045        ///////////////////
1046
1047        i2=lstrlen(sourceOfParams)-2;
1048
1049        int sw_as=0;
1050        for(;i2>0;i2--){
1051            if(sourceOfParams[i2]==')') break;
1052
1053            if(sourceOfParams[i2]==1&&sourceOfParams[i2+1]==ESC_AS){
1054                i2+=2;
1055                i3=0;
1056                while(sourceOfParams[i2]=='*') temporary[i3++]=sourceOfParams[i2++];
1057                for(;;i2++,i3++){
1058                    if(!IsVariableChar(sourceOfParams[i2])){
1059                        temporary[i3]=0;
1060                        break;
1061                    }
1062                    temporary[i3]=sourceOfParams[i2];
1063                }
1064                compiler.StringToType( temporary, this->returnType );
1065                if( this->returnType.IsNull() ) SmoothieException::Throw(3,temporary,nowLine);
1066
1067                sw_as=1;
1068                break;
1069            }
1070        }
1071    }
1072    else{
1073        //戻り値なしのSub定義
1074        this->returnType.SetNull();
1075    }
1076
1077    //戻り値のエラーチェック
1078    if( IsFunction() ){
1079        // Function定義
1080
1081        if( this->ReturnType().IsNull() ){
1082            // 戻り値がない
1083            SmoothieException::Throw(26,this->GetName(),nowLine);
1084        }
1085    }
1086    else{
1087        if( !this->ReturnType().IsNull() ){
1088            // Sub定義なのに、戻り値がある
1089            SmoothieException::Throw(38,this->GetName(),nowLine);
1090        }
1091    }
1092
1093    return true;
1094}
1095
1096int ProcPointers::Add( const string &typeExpression )
1097{
1098    DWORD dwProcType = (DWORD)typeExpression[2];
1099    const string &paramStr = typeExpression.substr( 3 );
1100
1101    Procedure::Kind kind = Procedure::Sub;
1102    if( dwProcType == ESC_FUNCTION ){
1103        kind = Procedure::Function;
1104    }
1105
1106    ProcPointer *pProcPointer = new ProcPointer( kind );
1107
1108    //buffer[0]は'('となっている
1109    extern int cp;
1110    pProcPointer->SetParamsAndReturnType( paramStr.c_str(), cp );
1111
1112    this->push_back( pProcPointer );
1113
1114    return (int)this->size()-1;
1115}
1116
1117void ProcPointers::Clear()
1118{
1119    ProcPointers &procPointers = *this;
1120    BOOST_FOREACH( ProcPointer *pProcPointer, procPointers ){
1121        delete pProcPointer;
1122    }
1123    this->clear();
1124}
Note: See TracBrowser for help on using the repository browser.