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

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

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

File size: 25.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::AddUserProc( const NamespaceScopes &namespaceScopes, const NamespaceScopesCollection &importedNamespaces, char *buffer,int nowLine,bool isVirtual,CClass *pobj_c, bool isStatic, char *interfaceName )
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        char parentName[VN_SIZE], memberName[VN_SIZE];
549        ReferenceKind refKind;
550        if( SplitMemberName( temporary, parentName, memberName, refKind ) )
551        {
552            if( pobj_c )
553            {
554                if( interfaceName )
555                {
556                    lstrcpy( interfaceName, parentName );
557                }
558                else
559                {
560                    SetError();
561                    return NULL;
562                }
563
564                char dummyMemberName[VN_SIZE];
565                if( SplitMemberName( memberName, parentName, dummyMemberName, refKind ) )
566                {
567                    SetError(69,temporary,nowLine);
568                    return NULL;
569                }
570            }
571            else
572            {
573                SetError(68,temporary,nowLine);
574                return NULL;
575            }
576
577            lstrcpy( temporary, memberName );
578        }
579    }
580
581    if( isMacro ){
582        //大文字に変換
583        CharUpper(temporary);
584
585        //マクロ関数の場合は名前リストに追加
586        macroNames.push_back( temporary );
587    }
588
589    if(!pobj_c){
590        //クラスメンバ以外の場合のみ
591        //重複チェック
592
593        if(GetDeclareHash(temporary)){
594            SetError(15,temporary,nowLine);
595            return 0;
596        }
597    }
598
599    // 識別ID
600    static int id_base=0;
601
602    UserProc *pUserProc = new UserProc( namespaceScopes, importedNamespaces, temporary, kind, isMacro, isCdecl, isExport, (id_base++) );
603    pUserProc->SetParentClass( pobj_c );
604    if( Smoothie::isFullCompile ){
605        // すべての関数・メソッドをコンパイルする
606        pUserProc->Using();
607    }
608
609    // 親インターフェイスをセット
610    if( interfaceName && interfaceName[0] )
611    {
612        ::Interface *pTargetInterface = NULL;
613        BOOST_FOREACH( ::Interface *pInterface, pobj_c->GetInterfaces() )
614        {
615            if( pInterface->GetClass().GetName() == interfaceName )
616            {
617                pTargetInterface = pInterface;
618                break;
619            }
620        }
621        pUserProc->SetInterface( pTargetInterface );
622    }
623
624    if(isExport){
625        pUserProc->Using();
626    }
627
628    // パラメータを解析
629    // ※第1パラメータにに指定するデータの例:"( s As String ) As String"
630    pUserProc->SetParamsAndReturnType( buffer + i, nowLine, isStatic );
631
632    pUserProc->_paramStr = buffer + i;
633
634    // ハッシュに追加
635    if( !Insert( pUserProc, nowLine ) )
636    {
637        return NULL;
638    }
639
640    return pUserProc;
641}
642void UserProcs::EnumGlobalProcs( const char *simpleName, const char *localName, std::vector<const UserProc *> &subs )
643{
644    ///////////////////////////
645    // グローバル関数を検索
646    ///////////////////////////
647
648    // ハッシュ値を取得
649    UserProc *pUserProc = GetHashArrayElement( simpleName );
650    while(pUserProc){
651        if( pUserProc->IsGlobalProcedure() ){
652            if( pUserProc->IsEqualSymbol( localName ) ){
653                subs.push_back( pUserProc );
654            }
655        }
656
657        pUserProc=pUserProc->GetChainNext();
658    }
659}
660
661bool DllProc::SetParamsAndReturnType( const char *sourceOfParams, int nowLine ){
662    int i = 0;
663    int i2,i3,sw;
664    char temporary[8192],temp2[VN_SIZE];
665
666    //ソースコードの位置
667    this->codePos = nowLine;
668
669    //パラメータ
670    if(sourceOfParams[i]!='('){
671        SmoothieException::Throw(1,NULL,nowLine);
672        return 0;
673    }
674    i++;
675
676    while(1){
677        if(sourceOfParams[i]==')') break;
678
679        //ByRef
680        bool isRef;
681        if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_BYVAL){
682            isRef = false;
683            i+=2;
684        }
685        else if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_BYREF){
686            isRef = true;
687            i+=2;
688        }
689        else isRef = false;
690
691        //パラメータ名
692        bool isArray = false;
693        Subscripts subscripts;
694        char name[VN_SIZE];
695        sw=0;
696        for(i2=0;;i++,i2++){
697            if(sourceOfParams[i]=='('){
698                if(!sw) sw=1;
699
700                i3=GetStringInPare(name+i2,sourceOfParams+i);
701                i2+=i3-1;
702                i+=i3-1;
703                continue;
704            }
705            if(sourceOfParams[i]=='['){
706                if(!sw) sw=1;
707
708                i3=GetStringInBracket(name+i2,sourceOfParams+i);
709                i2+=i3-1;
710                i+=i3-1;
711                continue;
712            }
713            if(!IsVariableChar(sourceOfParams[i])){
714                name[i2]=0;
715                break;
716            }
717            name[i2]=sourceOfParams[i];
718        }
719        if(sw){
720            //配列パラメータ
721            if( isRef == false ) SmoothieException::Throw(29,NULL,nowLine);
722            isArray = true;
723
724            if((name[i2-2]=='('&&name[i2-1]==')')||
725                (name[i2-2]=='['&&name[i2-1]==']'))
726            {
727                subscripts.push_back( LONG_MAX );
728
729                name[i2-2]=0;
730            }
731            else{
732                GetArrange(name,temp2,subscripts);
733                lstrcpy(name,temp2);
734            }
735
736            i2=lstrlen(name);
737        }
738
739        //型
740        Type type( DEF_NON );
741        if(lstrcmp(name,"...")==0) type.SetBasicType( DEF_ELLIPSE );
742        else if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_AS){
743            i+=2;
744
745            i2=0;
746            while(sourceOfParams[i]=='*'){
747                temporary[i2]=sourceOfParams[i];
748                i++;
749                i2++;
750            }
751            for(;;i++,i2++){
752                if(!IsVariableChar(sourceOfParams[i])){
753                    if(sourceOfParams[i]==1&&(sourceOfParams[i+1]==ESC_FUNCTION||sourceOfParams[i+1]==ESC_SUB)){
754                        temporary[i2++]=sourceOfParams[i++];
755                        temporary[i2]=sourceOfParams[i];
756                        continue;
757                    }
758                    temporary[i2]=0;
759                    break;
760                }
761                temporary[i2]=sourceOfParams[i];
762            }
763
764            compiler.StringToType( temporary, type );
765
766            if( type.IsNull() ){
767                SmoothieException::Throw(3,temporary,nowLine);
768                type.SetBasicType( DEF_PTR_VOID );
769            }
770        }
771        else{
772            type.SetBasicType( Type::GetBasicTypeFromSimpleName(temporary) );
773            SmoothieException::Throw(-103,temporary,nowLine);
774        }
775
776        Parameter *pParam = new Parameter( name, type, isRef );
777        if( isArray ){
778            pParam->SetArray( subscripts );
779        }
780
781        //パラメータを追加
782        this->params.push_back( pParam );
783
784        if(sourceOfParams[i]==','){
785            i++;
786            continue;
787        }
788        else if(sourceOfParams[i]==')') continue;
789        else{
790            SmoothieException::Throw(1,NULL,nowLine);
791            break;
792        }
793    }
794    i++;
795
796    if(sourceOfParams[i]){
797        ///////////////////
798        // 戻り値を取得
799        ///////////////////
800
801        i2=lstrlen(sourceOfParams)-2;
802
803        int sw_as=0;
804        for(;i2>0;i2--){
805            if(sourceOfParams[i2]==')') break;
806
807            if(sourceOfParams[i2]==1&&sourceOfParams[i2+1]==ESC_AS){
808                i2+=2;
809                i3=0;
810                while(sourceOfParams[i2]=='*') temporary[i3++]=sourceOfParams[i2++];
811                for(;;i2++,i3++){
812                    if(!IsVariableChar(sourceOfParams[i2])){
813                        temporary[i3]=0;
814                        break;
815                    }
816                    temporary[i3]=sourceOfParams[i2];
817                }
818                compiler.StringToType( temporary, this->returnType );
819                if( this->returnType.IsNull() ) SmoothieException::Throw(3,temporary,nowLine);
820
821                sw_as=1;
822                break;
823            }
824        }
825    }
826    else{
827        //戻り値なしのSub定義
828        this->returnType.SetNull();
829    }
830
831    return true;
832}
833
834void DllProcs::Add(const NamespaceScopes &namespaceScopes, char *buffer,int nowLine){
835    int i2;
836
837    int i=0;
838
839    //Sub/Function
840    Procedure::Kind kind = Procedure::Sub;
841    if(buffer[i]==ESC_SUB){
842    }
843    else if(buffer[i]==ESC_FUNCTION){
844        kind = Procedure::Function;
845    }
846    else{
847        SetError(1,NULL,nowLine);
848        return;
849    }
850    i++;
851
852    //プロシージャ名
853    char procName[VN_SIZE];
854    bool isCdecl = false;
855    for(i2=0;;i++,i2++){
856        if(buffer[i]==1&&buffer[i+1]==ESC_CDECL){
857            isCdecl = true;
858
859            i+=2;
860            procName[i2]=0;
861            break;
862        }
863        if(buffer[i]==','){
864            procName[i2]=0;
865            break;
866        }
867        if(buffer[i]=='\0'){
868            SetError(1,NULL,nowLine);
869            return;
870        }
871        procName[i2]=buffer[i];
872    }
873    i++;
874
875    //ユーザー定義関数との重複チェック
876    if(GetSubHash(procName)){
877        SetError(15,procName,nowLine);
878        return;
879    }
880
881
882    //ライブラリ
883    char dllFileName[MAX_PATH];
884    i = GetOneParameter( buffer, i, dllFileName );
885    Type resultType;
886    _int64 i64data;
887    if( !StaticCalculation( true, dllFileName, 0, &i64data, resultType ) ){
888        return;
889    }
890    if( resultType.GetBasicType() != typeOfPtrChar ){
891        SetError(1,NULL,nowLine);
892        return;
893    }
894    lstrcpy( dllFileName, (char *)i64data );
895    CharUpper(dllFileName);
896    if(!strstr(dllFileName,".")){
897        lstrcat(dllFileName,".DLL");
898        if(lstrlen(dllFileName)>=16){
899            SetError(7,NULL,nowLine);
900            return;
901        }
902    }
903
904    //エイリアス
905    char alias[VN_SIZE];
906    i = GetOneParameter( buffer, i, alias );
907    if( alias[0] ){
908        if( !StaticCalculation( true, alias, 0, &i64data, resultType ) ){
909            return;
910        }
911        if( resultType.GetBasicType() != typeOfPtrChar ){
912            SetError(1,NULL,nowLine);
913            return;
914        }
915        lstrcpy( alias, (char *)i64data );
916    }
917    else{
918        //省略されたときは関数名
919        lstrcpy( alias, procName );
920    }
921
922
923    // オブジェクトを生成
924    DllProc *pDllProc = new DllProc( namespaceScopes, procName, kind, isCdecl, dllFileName, alias );
925
926    // パラメータを解析
927    // ※第1パラメータにに指定するデータの例:"( s As String ) As String"
928    pDllProc->SetParamsAndReturnType( buffer + i, nowLine );
929
930    // パラメータのエラーチェック
931    BOOST_FOREACH( const Parameter *pParam, pDllProc->Params() ){
932        if( pParam->IsObject() ){
933            SetError(25,pParam->GetVarName(),nowLine);
934        }
935        if( !pParam->IsRef() ){
936            if( pParam->IsStruct() ){
937                SetError(28,pParam->GetVarName(),nowLine);
938            }
939        }
940    }
941
942    //戻り値のエラーチェック
943    if( pDllProc->IsFunction() ){
944        // Function定義
945
946        if( pDllProc->ReturnType().IsObject() ){
947            // DLL関数ではオブジェクトを戻り値にできない
948            SetError(40,pDllProc->GetName(),nowLine);
949        }
950    }
951
952    // ハッシュマップに追加
953    this->Put( pDllProc );
954}
955
956bool ProcPointer::SetParamsAndReturnType( const char *sourceOfParams, int nowLine ){
957    int i = 0;
958    int i2,i3,sw;
959    char temporary[8192],temp2[VN_SIZE];
960
961    //ソースコードの位置
962    this->codePos = nowLine;
963
964    //パラメータ
965    if(sourceOfParams[i]!='('){
966        SmoothieException::Throw(1,NULL,nowLine);
967        return 0;
968    }
969    i++;
970    while(1){
971        if(sourceOfParams[i]==')') break;
972
973        //ByRef
974        bool isRef;
975        if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_BYVAL){
976            isRef = false;
977            i+=2;
978        }
979        else if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_BYREF){
980            isRef = true;
981            i+=2;
982        }
983        else isRef = false;
984
985        //パラメータ名
986        bool isArray = false;
987        Subscripts subscripts;
988        char name[VN_SIZE];
989        sw=0;
990        for(i2=0;;i++,i2++){
991            if(sourceOfParams[i]=='('){
992                if(!sw) sw=1;
993
994                i3=GetStringInPare(name+i2,sourceOfParams+i);
995                i2+=i3-1;
996                i+=i3-1;
997                continue;
998            }
999            if(sourceOfParams[i]=='['){
1000                if(!sw) sw=1;
1001
1002                i3=GetStringInBracket(name+i2,sourceOfParams+i);
1003                i2+=i3-1;
1004                i+=i3-1;
1005                continue;
1006            }
1007            if(!IsVariableChar(sourceOfParams[i])){
1008                name[i2]=0;
1009                break;
1010            }
1011            name[i2]=sourceOfParams[i];
1012        }
1013        if(sw){
1014            //配列パラメータ
1015            if( isRef == false ) SmoothieException::Throw(29,NULL,nowLine);
1016            isArray = true;
1017
1018            if((name[i2-2]=='('&&name[i2-1]==')')||
1019                (name[i2-2]=='['&&name[i2-1]==']'))
1020            {
1021                subscripts.push_back( LONG_MAX );
1022
1023                name[i2-2]=0;
1024            }
1025            else{
1026                GetArrange(name,temp2,subscripts);
1027                lstrcpy(name,temp2);
1028            }
1029
1030            i2=lstrlen(name);
1031        }
1032
1033        //型
1034        Type type( DEF_NON );
1035        if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_AS){
1036            i+=2;
1037
1038            i2=0;
1039            while(sourceOfParams[i]=='*'){
1040                temporary[i2]=sourceOfParams[i];
1041                i++;
1042                i2++;
1043            }
1044            for(;;i++,i2++){
1045                if(!IsVariableChar(sourceOfParams[i])){
1046                    if(sourceOfParams[i]==1&&(sourceOfParams[i+1]==ESC_FUNCTION||sourceOfParams[i+1]==ESC_SUB)){
1047                        temporary[i2++]=sourceOfParams[i++];
1048                        temporary[i2]=sourceOfParams[i];
1049                        continue;
1050                    }
1051                    temporary[i2]=0;
1052                    break;
1053                }
1054                temporary[i2]=sourceOfParams[i];
1055            }
1056
1057            compiler.StringToType( temporary, type );
1058
1059            if( type.IsNull() ){
1060                SmoothieException::Throw(3,temporary,nowLine);
1061                type.SetBasicType( DEF_PTR_VOID );
1062            }
1063        }
1064        else{
1065            type.SetBasicType( Type::GetBasicTypeFromSimpleName(temporary) );
1066            SmoothieException::Throw(-103,temporary,nowLine);
1067        }
1068
1069        Parameter *pParam = new Parameter( name, type, isRef );
1070        if( isArray ){
1071            pParam->SetArray( subscripts );
1072        }
1073
1074        //パラメータを追加
1075        this->params.push_back( pParam );
1076
1077        if(sourceOfParams[i]==','){
1078            i++;
1079            continue;
1080        }
1081        else if(sourceOfParams[i]==')') continue;
1082        else{
1083            SmoothieException::Throw(1,NULL,nowLine);
1084            break;
1085        }
1086    }
1087    i++;
1088
1089    if(sourceOfParams[i]){
1090        ///////////////////
1091        // 戻り値を取得
1092        ///////////////////
1093
1094        i2=lstrlen(sourceOfParams)-2;
1095
1096        int sw_as=0;
1097        for(;i2>0;i2--){
1098            if(sourceOfParams[i2]==')') break;
1099
1100            if(sourceOfParams[i2]==1&&sourceOfParams[i2+1]==ESC_AS){
1101                i2+=2;
1102                i3=0;
1103                while(sourceOfParams[i2]=='*') temporary[i3++]=sourceOfParams[i2++];
1104                for(;;i2++,i3++){
1105                    if(!IsVariableChar(sourceOfParams[i2])){
1106                        temporary[i3]=0;
1107                        break;
1108                    }
1109                    temporary[i3]=sourceOfParams[i2];
1110                }
1111                compiler.StringToType( temporary, this->returnType );
1112                if( this->returnType.IsNull() ) SmoothieException::Throw(3,temporary,nowLine);
1113
1114                sw_as=1;
1115                break;
1116            }
1117        }
1118    }
1119    else{
1120        //戻り値なしのSub定義
1121        this->returnType.SetNull();
1122    }
1123
1124    //戻り値のエラーチェック
1125    if( IsFunction() ){
1126        // Function定義
1127
1128        if( this->ReturnType().IsNull() ){
1129            // 戻り値がない
1130            SmoothieException::Throw(26,this->GetName(),nowLine);
1131        }
1132    }
1133    else{
1134        if( !this->ReturnType().IsNull() ){
1135            // Sub定義なのに、戻り値がある
1136            SmoothieException::Throw(38,this->GetName(),nowLine);
1137        }
1138    }
1139
1140    return true;
1141}
1142
1143int ProcPointers::Add( const string &typeExpression )
1144{
1145    DWORD dwProcType = (DWORD)typeExpression[2];
1146    const string &paramStr = typeExpression.substr( 3 );
1147
1148    Procedure::Kind kind = Procedure::Sub;
1149    if( dwProcType == ESC_FUNCTION ){
1150        kind = Procedure::Function;
1151    }
1152
1153    ProcPointer *pProcPointer = new ProcPointer( kind );
1154
1155    //buffer[0]は'('となっている
1156    extern int cp;
1157    pProcPointer->SetParamsAndReturnType( paramStr.c_str(), cp );
1158
1159    this->push_back( pProcPointer );
1160
1161    return (int)this->size()-1;
1162}
1163
1164void ProcPointers::Clear()
1165{
1166    ProcPointers &procPointers = *this;
1167    BOOST_FOREACH( ProcPointer *pProcPointer, procPointers ){
1168        delete pProcPointer;
1169    }
1170    this->clear();
1171}
Note: See TracBrowser for help on using the repository browser.